Book Map
한 주제를 어떤 순서로 읽으면 되는지 한 지도로 보여주는 독서 로드맵 - 책 추천이 아니라 "경로"를 보여주는 게 목표.
- React
- TypeScript
- Hono
- Reading
랜딩 - "책을 추천하는 게 아니라, 읽는 순서를 보여줍니다" 한 줄 카피와 순서·연결·내 위치 세 가지 가치
진행 현황 - 주제별 진도(1권 / 총 7)와 권당 상태를 한 화면에
주제 지도 - 책 카드가 경로 위에 배치되고 "현재 여기" 마커로 위치를 표시한다
책 상세 - 상태·별점·구매 링크와 "왜 읽어야 하는가·읽고 나면 얻는 것·읽기 전 알아두면 좋은 책들"을 정형화
독후감 + AI 피드백 - 작성한 글을 "잘 읽어낸 점·보완하면 좋을 점·한 줄 평"으로 돌려준다
독후감 끝 - "우리 지도 안에서·지도 밖에서" 두 줄로 다음 책을 잇는다
내 서재 - 읽은 책·읽는 중·읽을 책 세 칸으로 상태를 한 곳에 모은다
AI 추천 - 완독한 책의 독후감을 바탕으로 "지도 안 다음 책·지도 밖 책"을 함께 제안
Setup
- Problem
책 추천 리스트는 어디에나 있지만 "어떤 순서로 읽어야 하는지"의 지도가 없다. 입문자는 매번 다음 책을 고르는 데 시간을 쓰고, 사수는 "이거부터 봐" 한 마디로 끝낼 만한 답이 없다.
- Context
QA 엔지니어 14년 동안 "입문자에게 어떤 책부터 권할까"를 반복해서 마주한 데서 출발. 책의 가치는 한 권의 추천보다 한 주제의 경로를 잡는 데서 더 크게 나온다는 가설로 시작.
- Users
특정 주제를 처음 학습하려는 독학자, "어디서부터 시작하지" 묻는 후배에게 짧은 한 마디로 답하고 싶은 사수.
- Hypothesis
책을 카드 카탈로그로 늘어놓는 대신 한 장의 지도로 순서·연결·내 위치를 보여주면, "다음에 뭘 읽지"가 검색이 아니라 한눈 확인으로 바뀐다.
Build
- What I did
- 주제별 독서지도 데이터 모델 - 책 사이의 선후 관계와 단계 구분
- 지도 화면 - 책 카드를 경로 위에 배치하고 "현재 여기"로 진도 표시
- 책 상세 - "왜 읽어야 하는가·읽고 나면 얻는 것·읽기 전 알아두면 좋은 책들"을 정형화
- 독후감 + AI 피드백 - 작성한 글을 "잘 읽어낸 점·보완하면 좋을 점·한 줄 평"으로 회신하고 끝에 "지도 안 다음 책·지도 밖 책"을 함께 제안
- 내 서재 - 읽은 책·읽는 중·읽을 책을 한 곳에 모음, 별점·메모는 카드에서 바로 매김
- 프런트엔드는 정적으로도 동작, 백엔드(Hono + Neon Postgres + Drizzle + JWT)는 계정·진도 동기화·큐레이터 콘텐츠 수정용으로 분리
- Product decisions
- 책 "추천 리스트"를 의도적으로 만들지 않음 - 추천이 아니라 경로를 보여주는 정체성을 흐리지 않으려고
- 독후감 후 추천도 "지도 안 다음 책·지도 밖 책" 두 줄로 분리 - 같은 길에 머무를지 가지를 칠지 사용자가 선택
- 백엔드를 옵셔널 레이어로 - 회원가입 마찰 없이 진입 가능, 진도 동기화는 원할 때만
- 콘텐츠는 큐레이터가 코드 배포 없이 수정 가능하게 - 한 장의 지도가 시간 지나도 신뢰를 유지하려면 운영자가 닿을 수 있어야 한다
- QA considerations
- 비로그인 localStorage 진도와 로그인 서버 진도가 어긋나지 않는가 - 계정 가져오기 미지원을 화면에 정직하게 명시했는가
- 낙관적 업데이트(진도·별점 쓰기) 실패 시 이전 상태로 정확히 롤백되는가
- AI 응답이
tool_use구조를 못 만들면 502로 막아 깨진 노트가 독자에게 닿지 않는가 - AI 키가 없을 때 /api/ai/*만 503으로 떨어지고 지도·진도·메모·인증은 계속 서비스되는가(의존성 실패 격리)
- 부팅 시 zod 환경변수 fail-fast 검증으로 설정 오류가 조용히 통과하지 않는가
Outcome
- Metrics
Alpha 단계. 현재 3개 주제(창업·글쓰기·프로그래밍 입문) 등록, 사용자 수치는 측정 전.
- Result / Learning
프런트엔드만으로도 완결적으로 동작하는 상태에서 "한 주제부터 완성도 높이고 신호 보기"로 다음 라운드를 정의. 큐레이터가 늘었을 때 "한 장의 지도에 들어가는 규칙"이 가장 큰 디자인 과제로 남음.
진행 과정 (기획 → 개발)
문제·가설에서 스코프·스펙(SSOT)·개발·QA 게이트·배포까지, 같은 틀로 이 앱을 어떻게 기획하고 끌고 갔는지.
진행 과정 (기획 → 개발)
문제 · 가설
책 추천 리스트는 넘쳐도 '무엇을 어떤 순서로 읽어야 하는지'의 지도는 없다는 게, 14년 QA로 후배에게 책을 권할 때마다 반복해서 마주친 문제다. 가설은 책을 카탈로그로 늘어놓는 대신 순서·연결·내 위치(책별 예정/읽는 중/완료 상태)를 한 장의 지도로 보여주면 '다음에 뭘 읽지'가 검색이 아니라 한눈 확인이 된다는 것.
역량 · 문제 정의 · 가설
스코프 · 우선순위
정체성을 '추천 카탈로그·독서 기록'이 아니라 '순서를 보여주는 지도'로 고정하고(README: 핵심은 추천이 아니라 경로, 기록이 아니라 지도), 넓은 커버리지 대신 시드를 3개 주제·20권으로 의도적으로 좁게 냈다. 회원가입 마찰을 줄이려 지도는 비로그인으로도 쓸 수 있게 진도를 localStorage(book-map:progress:v1)에 두고 로그인하면 서버 기반 기기 간 진도로 전환되지만, 비로그인 진도를 계정으로 가져오는 것은 아직 지원하지 않는다(진행 페이지에 '로그인 후 별도 가져오기는 아직 지원되지 않습니다'로 명시).
역량 · 스코핑 · 우선순위
스펙 우선 (SSOT)
별도 PRD·기획 문서는 없고, 데이터 모델(server/src/db/schema.ts)과 시드 콘텐츠(server/src/db/seed-data.ts)가 사실상 SSOT 역할을 한다. AI 응답은 tool_use input_schema로 형태를 계약처럼 고정했고(server/src/lib/ai.ts의 callClaudeStructured), 루트·server 두 README가 API 표면을 인터페이스 명세로 남긴다.
역량 · 스펙 · 문서화
개발 · 이터레이션
프런트엔드를 먼저 동작하게 만든 뒤 Hono 백엔드를 스캐폴딩하고 API 호출 구조로 전환했다(커밋 149bd8a → ac82b84 → a604313 순서 그대로, a604313에서 정적 src/data/maps.ts 삭제). 스키마는 초기 마이그레이션 위에 메모 테이블·별점 컬럼·AI 출력 테이블을 마이그레이션 3개로 additive하게 얹어 총 4개이고, 로그인 사용자의 진도·별점 쓰기는 TanStack Query 낙관적 업데이트에 실패 시 이전 상태로 롤백을 걸었다.
역량 · 실행 · 전달
검증 (QA 게이트)
QA 배경은 자동화 테스트 스위트가 아니라(아직 리포에 없다) '코드 안의 계약·실패 격리'로 나타난다. 부팅 시 zod로 환경변수를 fail-fast 검증(env.ts safeParse 실패 시 process.exit)하고, AI 응답이 tool_use 형태를 못 만들면 502로 막아 깨진 출력이 독자에게 닿지 않게 했으며 결과는 upsert(onConflictDoUpdate)로 영속화해 재방문 때 같은 답을 보여준다. AI 키가 없으면 /api/ai/*만 503으로 떨어지고 지도·진도·메모·인증은 계속 서비스돼, 가장 불안정한 의존성의 실패를 백엔드 층에서 격리했다.
역량 · 품질 · 리스크
배포
프런트엔드는 Cloudflare Pages(book-map.pages.dev), 백엔드는 render.yaml Blueprint로 Render 싱가포르 리전에 올리고 /healthz로 헬스체크한다. 배포 중 NODE_ENV=production이 빌드 도구(devDependencies)를 건너뛰는 문제를 buildCommand의 npm install --include=dev로 잡은 게 실제 커밋(c2022bc)으로 남아 있고, 현재는 3개 주제(창업·글쓰기·프로그래밍 입문)·20권이 시드된 0.1.0 alpha 상태로 사용자 수치는 측정 전이다.
역량 · 릴리스
- Tech stack
- React 18
- TypeScript
- Vite
- React Router v6
- Tailwind
- Hono
- Drizzle ORM
- Neon Postgres
- JWT
- Cloudflare Pages
- Render
- Links