Easy-to-manage touch screens
무료 오픈소스 터치스크린으로 USB 설정 가이드, 드래그‑드롭 편집기, 로컬 제어를 제공하며 Home Assistant용으로 제작되었습니다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기중구: 중고차 구매가이드 — 차종·연식별 고질병과 매장 점검 가이드
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗차종과 연식을 넣으면 중고차를 살 때 확인할 고질병과 체크 포인트를 알려주는 서비스.
학습 프로젝트입니다. 프론트엔드 개발자가 백엔드(NestJS·Prisma·PostgreSQL)·인증·테스트·배포까지 새 스택을 직접 익히려고 만들고 있습니다. 무엇을 새로 익혔는지, 폴더를 왜 이렇게 나눴는지는 학습 노트에 정리했습니다. 기획은 plan.md, 회고는 retrospective.md.
api/ NestJS + Prisma + PostgreSQL · web/ Next.js + Tailwind (포트 3201) · e2e/ Playwright| 기능 | 누가 | 이유 |
|---|---|---|
| 차종·연식별 고질병, 구매 시 확인법 | DB (사람이 검증) | 돈이 걸린 사실 정보라 AI의 그럴듯한 거짓말(환각)을 피해야 함 |
| 아무것도 모를 때 "무엇부터 알아볼지" | AI | 정답이 하나가 아닌 안내·설명 |
| 용도·예산별 차종 추천 | AI → DB 연결 | 추천 차종에 DB 고질병 링크를 붙여 줌 |
고질병 데이터는 초안(DRAFT)으로 들어가고, 검토 요청 → 관리자 승인(검증됨) 또는 반려를 거칩니다. 승인은 출처 URL이 있어야만 됩니다(서버 규칙). 아래 "고질병 심사 흐름" 참고. 샘플 데이터(세대 이름·엔진·미션·고질병·점검 포인트)는 전부 Claude가 쓴 초안이라 사실 확인이 필요합니다.
준비물: Node 22+, Docker Desktop. 패키지 매니저는 pnpm만 씁니다 (npm·yarn으로 설치하면 안내 메시지와 함께 멈춰요).
npm install -g pnpm # 처음 한 번만 (또는 brew install pnpm)
pnpm install # 저장소 맨 위 폴더에서. api·web을 한 번에 설치하고, .env가 없으면 .env.example을 복사해 둡니다
pnpm db:setup # 처음 한 번: PostgreSQL 컨테이너(포트 5434) + 테이블 생성 + 샘플 데이터 (⚠️ 기존 데이터는 지워짐)
pnpm dev # API http://localhost:3200 (문서 /docs) + 화면 http://localhost:3201 동시 실행
corepack enable로 pnpm을 받는 방법도 있지만, Node 22.13 이하의 corepack은 서명 키가 오래돼 Cannot find matching keyid 오류로 pnpm이 실행되지 않습니다. 그럴 땐 corepack disable 후 위처럼 npm으로 설치하세요.pnpm --dir api db:up → pnpm dev만 하면 됩니다.pnpm --dir api dev / pnpm --dir web dev.car-check)를 열면 위쪽 실행 목록에 전체 실행 (api + web), api, web, DB 처음 준비 (데이터 초기화) 가 나옵니다 (.run/ 폴더).package.json의 packageManager 값을 보고 보통 자동으로 잡힙니다)pnpm install을 먼저 한 번 실행한 뒤 실행 버튼을 누르세요.api/.env) — 셋 중 하나| 하고 싶은 것 | 설정 | AI 가이드 화면 |
|---|---|---|
| AI 없이 실행 (기본값) | GEMINI_API_KEY="", USE_MOCK_AI=false | "AI 꺼짐" 안내. 차종 검색·고질병·데이터 관리는 정상 |
| 키 없이 AI 화면 흐름만 확인 | USE_MOCK_AI=true | 미리 준비된 샘플 답변 (비용·할당량 0) |
| 실제 Gemini 사용 | GEMINI_API_KEY="발급받은 키", USE_MOCK_AI=false | 실제 답변 |
gemini-flash-latest(최신 Flash). 바꾸려면 GEMINI_MODEL.env를 바꾸면 API 서버를 다시 시작하세요.AI_GLOBAL_PER_MIN)까지이고 넘으면 429와 "몇 초 뒤 다시" 안내를 줍니다. 둘 다 서버 메모리에 저장하므로 서버를 여러 대로 늘리면 Redis로 옮겨야 합니다./admin과 쓰기 API(POST·PATCH·DELETE)는 로그인이 필요합니다. 조회(GET)와 AI 질문은 누구나 쓸 수 있어요.
| 역할 | 할 수 있는 것 | 정하는 곳 (api/.env) |
|---|---|---|
| ADMIN | 모든 수정 + "검증됨" 처리 + 삭제 + 차종 추가 | ADMIN_EMAILS |
| EDITOR | 고질병 초안·점검 포인트 작성, 초안 수정, 검토 요청. 승인·반려·검증 취소·삭제는 불가 | EDITOR_EMAILS |
| 그 외 구글 계정 | 로그인 거절 |
@Roles("ADMIN", "EDITOR"), 로그인 없이 되는 곳은 @Public()로 표시합니다(api/src/auth/auth.guard.ts). 새 API를 만들고 깜빡해도 열려 있지 않아요.구글 로그인 켜기 (한 번만)
http://localhost:3201 추가 (배포하면 실제 화면 주소도)api/.env의 GOOGLE_CLIENT_ID에 넣고 API 다시 시작 (클라이언트 보안 비밀번호는 필요 없음)구글 설정 전에도 AUTH_DEV_LOGIN=true면 관리 화면에서 이메일만으로 로그인할 수 있어요(개발·테스트용, 운영 환경에서는 항상 꺼짐). 이메일은 ADMIN_EMAILS·EDITOR_EMAILS에 있어야 합니다.
초안 ──검토 요청──▶ 검토 중 ──승인(출처 필수, ADMIN)──▶ 검증됨
▲ ◀──요청 취소── └──반려(사유 필수, ADMIN)──▶ 반려 ──다시 고치기──▶ 초안
└────────────────── 검증 취소(사유 필수, ADMIN) ◀── 검증됨
api/src/issues/issue-workflow.ts의 표 하나에만 있고, 표에 없는 전이(초안 → 검증됨 직행 등)는 서버가 거절합니다. 관리 화면 버튼도 이 표로 만들어 서버가 내려줍니다.IssueHistory): 작성·수정·상태 전이마다 누가·언제·무엇을(수정한 칸의 전·후)·왜(사유)를 남깁니다. 변경과 이력은 하나의 트랜잭션으로 저장해서 이력 없는 변경이 생기지 않습니다.| 주소 | 내용 |
|---|---|
/ | 사이트 소개: 어려운 점 3가지 → 사용 방법 → 시작 버튼 |
/cars | 차종 선택: 검색 + 제조사 탭(국산 각각, 수입 묶음) + 차 종류 필터(RV/SUV·세단·경차) → 차 이름 카드(이미지 없이 이름 + 차 종류) |
/generations/[maker]/[name] | 세대·연식 선택: "올 뉴 투싼 (2015~2018)"처럼 고르기, 연식 입력으로 좁히기 |
/cars/[id] | 고질병 리포트: 엔진·미션 요약 → 고질병(검증됨 먼저) → 매장 체크리스트(브라우저에 저장) → 공통 점검 |
/cars/[id]/inspect | 매장 점검 가이드: 스펙별 주의점(DCT → 저속 꿀렁거림 등) → 본넷 그림 + 빨간 동그라미 → 시운전 순서 |
/guide | AI: 무엇부터 알아볼지, 용도별 추천 (추천 차종 → 세대 선택으로 연결) |
/admin | 구글 로그인 필요. 차종·엔진 추가, 고질병 추가·검증·삭제, 이 차 본넷 점검 포인트 추가 |
조회 화면은 ISR(/cars, /generations/…, /cars/[id], /cars/[id]/inspect): 서버가 API를 불러 화면을 만들어 저장해 두고, 다음 방문자부터는 저장된 화면을 그대로 줍니다(API 호출 없음). 1시간마다 뒤에서 새로 만들고, 관리 화면에서 데이터를 고치면 바로 지워져 다음 방문 때 반영됩니다(web/src/app/actions.ts). 체크리스트·필터처럼 움직이는 부분만 브라우저 컴포넌트(web/src/components/)입니다.
pnpm build 때 /cars를 미리 만들기 때문에 빌드할 때 API가 켜져 있어야 합니다. 나머지 화면은 첫 방문 때 만들어요.pnpm dev(개발 모드)에서는 저장하지 않고 매번 새로 만듭니다. 캐시 동작은 pnpm build && pnpm start로 확인하세요.api/prisma/schema.prisma)| 테이블 | 내용 |
|---|---|
CarModel | 세대 하나. name(투싼) + displayName(올 뉴 투싼) + 세대 코드 + 연식 구간 + 차급 + 차 종류(bodyType: 세단·SUV·경차·승합) |
Powertrain | 세대별 엔진·미션 조합 (연료, 미션 종류 AT·DCT·CVT·MT). 미션·연료만 넣으면 주의점이 자동으로 붙음 (api/src/cars/powertrain-tips.ts) |
CarIssue | 고질병. 초안(DRAFT) → 검토 중(IN_REVIEW) → 검증됨(VERIFIED, 출처 필수) / 반려(REJECTED) |
IssueHistory | 고질병 변경 이력: 작성·수정(바뀐 칸 전·후)·상태 전이(사유), 한 사람(User) |
User | 관리 화면에 로그인한 구글 계정 + 역할(ADMIN·EDITOR) |
InspectionPoint | 본넷 그림 위 빨간 동그라미. carModelId가 없으면 모든 차 공통, 있으면 그 차만(점선). 위치는 그림 기준 % |
스키마를 고치면 api 폴더에서 pnpm db:migrate (마이그레이션 + Prisma Client 재생성)를 실행하세요.
차종 데이터는 api/prisma/seed-data/(제조사별 파일)에 있습니다. 파일에 차종을 추가한 뒤 api 폴더에서 pnpm db:add-missing 을 실행하면 DB에 없는 것만 추가합니다(기존 데이터 유지). pnpm db:seed는 전부 지우고 다시 넣습니다.
| Method | Path | 설명 |
|---|---|---|
| GET | /cars/models | 차종 선택 화면용: 차 이름 단위 카드 |
| GET | /cars/generations?maker=현대&name=투싼 | 한 차종의 세대들 |
| GET | /cars/search?q=투싼&year=2015 | 이름·세대 이름·별칭 + 연식으로 찾기 |
| GET | /cars/:id | 리포트: 세대 + 엔진·미션 + 주의점 + 고질병 + 공통 점검 |
| GET | /cars/:id/inspection | 점검 가이드: 주의점 + 본넷 포인트 + 시운전 순서 |
| GET | /cars | 세대 전체 (관리용) |
| GET · POST | /auth/config, /auth/google, /auth/dev, /auth/me | 로그인 설정 · 구글 로그인 · 개발용 로그인 · 내 정보 |
| POST | /cars | 세대 + 엔진·미션 추가 🔒ADMIN |
| GET | /issues?carModelId=2 | 관리 화면: 반려 포함 전부 + 이력 + 내가 누를 수 있는 심사 버튼 🔒ADMIN·EDITOR |
| POST · PATCH | /issues, /issues/:id | 고질병 추가(항상 초안)·내용 수정(초안·반려만) 🔒ADMIN·EDITOR |
| POST | /issues/:id/transition | 상태 전이 {"to":"VERIFIED","sourceUrl":"..."} / {"to":"REJECTED","reason":"..."} 🔒역할은 심사 흐름 표대로 |
| DELETE | /issues/:id | 삭제(이력도 같이 지워짐. 틀린 정보는 반려 권장) 🔒ADMIN |
| POST · DELETE | /inspection-points, /inspection-points/:id | 본넷 점검 포인트 추가 🔒ADMIN·EDITOR, 삭제 🔒ADMIN |
🔒 표시는 Authorization: Bearer <로그인 토큰>이 필요합니다. API 문서(/docs)의 Authorize 버튼에 토큰을 넣으면 바로 시험할 수 있어요.
| GET | /health | 서버·DB 상태 (배포 헬스체크) |
| POST | /health/sentry-test | Sentry 연결 확인용 일부러 500 에러 🔒ADMIN |
| GET | /ai/status | AI 모드 (gemini / mock / off) |
| POST | /ai/guide · /ai/recommend | 무엇부터 알아볼지 · 용도별 추천 |
pnpm test # 단위 테스트 (Vitest, api)
pnpm typecheck # api·web·e2e 타입 체크
pnpm lint # web 린트
pnpm test:e2e # E2E (Playwright): 브라우저로 실제 화면을 눌러봄
E2E (e2e/): 테스트 전용으로 DB(car_check_e2e, 개발 DB와 별개)·API(3290)·화면(3291, 운영 빌드)을 띄운 뒤 모바일 크롬으로 확인합니다. 개발 서버가 떠 있어도 겹치지 않아요.
pnpm --dir e2e exec playwright install chromium (브라우저 설치). Docker DB(pnpm --dir api db:up)가 켜져 있어야 합니다.pnpm --dir e2e report로 화면·네트워크 기록(trace)을 볼 수 있어요.CI (.github/workflows/ci.yml): PR과 master 푸시마다 GitHub Actions에서 타입 체크·린트·단위 테스트 → E2E 순서로 돌립니다. DB는 Postgres 서비스 컨테이너, 실패하면 Playwright 리포트를 내려받을 수 있어요.
| 무엇 | 어디 | 설정 파일 |
|---|---|---|
| 화면 (Next.js) | Vercel (싱가포르) | web/vercel.json |
| API (NestJS) | Render 무료 (싱가포르) | render.yaml |
| DB (PostgreSQL) | Neon 무료 (싱가포르) | |
| 에러 수집 | Sentry (Next.js·NestJS 프로젝트 2개) | web/src/instrumentation*.ts, api/src/instrument.ts |
지금 배포된 곳 (2026-10-27)
| 무엇 | 주소 |
|---|---|
| 화면 | https://car-check-fawn-zeta.vercel.app |
| API | https://car-check-api-vfyd.onrender.com (/health로 상태 확인) |
api/.env.render(Render에 붙여 넣기), web/.env.vercel(Vercel에 붙여 넣기). 둘 다 저장소에 올라가지 않습니다(.git/info/exclude).WEB_ORIGIN·NEXT_PUBLIC_API_URL은 https://를 포함하고 끝에 /를 붙이지 않습니다.db:seed는 전부 지우고 다시 넣습니다. 운영 DB에 관리 화면에서 승인한 데이터가 생긴 뒤에는 운영 DB에 시드를 돌리지 말고 관리 화면으로 추가하세요.처음 배포 순서 (다시 만들 때)
-pooler가 들어간 주소)와 Direct.DATABASE_URL="<Direct 주소>" pnpm --dir api exec prisma migrate deploy → DATABASE_URL="<Direct 주소>" pnpm --dir api db:seedrender.yaml대로 생성. 비밀값 입력: DATABASE_URL(Pooled), DIRECT_URL(Direct), ADMIN_EMAILS, GOOGLE_CLIENT_ID, SENTRY_DSN(NestJS), GEMINI_API_KEY(선택). WEB_ORIGIN은 5번 뒤에 채움.web → 환경변수 NEXT_PUBLIC_API_URL(Render 주소), NEXT_PUBLIC_SENTRY_DSN(Next.js) → Deploy. 빌드 때 /cars를 미리 만들므로 Render API가 떠 있어야 합니다(잠들어 있으면 깨우느라 빌드가 조금 느려짐).WEB_ORIGIN에 Vercel 주소 → Google Cloud Console의 승인된 JavaScript 원본에 Vercel 주소 추가.https://<render 주소>/health → {"ok":true}. 관리자 토큰으로 POST /health/sentry-test를 부르면 Sentry에 테스트 에러가 들어옵니다.이후에는 master에 푸시하면 CI(GitHub Actions)가 모두 통과한 뒤에만 Render·Vercel이 자동으로 다시 배포하고, 새 마이그레이션은 Render가 켜질 때 적용합니다.
render.yaml의 autoDeployTrigger: checksPass (CI 통과 후 배포)기획과 일정은 docs/plan.md에 있습니다 (분류 화면 → 엔진룸 사진 → AI로 고질병 후보 모으기 → 커뮤니티 → 추천).