chaekmate 개발일지 — Next.js + FastAPI 마이그레이션 & 프로덕션 배포

Published

2026.04.19

chaekmate 개발일지 (2026-04-19)

오늘 한 일 요약

Streamlit MVP로 완성된 chaekmate를 FastAPI + Next.js 스택으로 마이그레이션하고, Fly.io(백엔드) + Vercel(프론트) 프로덕션 환경까지 배포 완료했다. 쿠키 기반 인증 관련 버그를 두 건 잡으며 로그인 플로우가 실제 브라우저에서 동작하는 것을 확인했다.


커밋 로그

시각(UTC) SHA 내용
01:37 fceeb90 fix(auth): OAuth state 쿠키와 JWT 세션 쿠키 이름 충돌 해결
01:46 ada4c59 feat(frontend): Next.js App Router — 랜딩·온보딩·SSE 채팅 페이지
02:54 b43b4ce Merge PR #3: FastAPI 백엔드 + Google OAuth + 스트리밍 채팅
03:13 23c946b refactor: Streamlit 앱 → scripts/ 로 이동 (유지보수 모드)
03:17 f4afc4c feat(deploy): Fly.io 백엔드 설정 (SQLite 볼륨, Tokyo 리전)
04:34 4a8d470 chore: Claude Code 로컬 MCP·설정 파일 gitignore 추가
07:58 a78b173 Merge PR #4: cleanup & deploy 브랜치 병합
08:29 15829ba fix(frontend): Next.js rewrite로 same-origin 쿠키 문제 해결
09:01 e3cda84 fix(auth): 로그아웃 시 Set-Cookie 헤더 누락 버그 수정

주요 작업 상세

Phase 1 완료 — FastAPI 백엔드 마이그레이션

기존 Streamlit의 비즈니스 로직(src/ 디렉토리)을 그대로 import해 FastAPI 라우터로 래핑했다. 재작성 없이 이식하는 방식을 택했기 때문에 추천 엔진·임베딩·DB 로직에는 변경이 없다.

구현된 엔드포인트 - GET /api/onboarding/books — 온보딩 그리드용 도서 18권 - POST /api/onboarding — 평점 제출 → 추천 후보 풀 생성 - POST /api/chat — Claude API SSE 스트리밍 - GET /api/auth/googleGET /api/auth/google/callback — Google OAuth 2.0 - GET /api/auth/me / POST /api/auth/logout

Phase 2 완료 — Next.js 프론트엔드

Next.js 16 + React 19 + TypeScript + Tailwind 조합으로 세 페이지를 구현했다.

  • 랜딩 / — Google 로그인 버튼, 로그인 상태면 /chat 자동 리다이렉트
  • 온보딩 /onboarding — 18권 그리드 + ❤️ 👎 ✨ ⏭️ 4단계 토글 평점 (MVP 결정사항 유지)
  • 채팅 /chatfetch + ReadableStream으로 SSE 수신, 타이핑 효과 렌더링, 추천 카드에 피드백 버튼

EventSource는 POST body를 지원하지 않아 fetch + ReadableStream으로 직접 스트림을 처리했다.

프로덕션 배포

서비스 플랫폼 비고
FastAPI 백엔드 Fly.io (Tokyo nrt) 1GB SQLite 볼륨, 유휴 시 자동 중지
Next.js 프론트엔드 Vercel -
DB SQLite (볼륨 마운트) 첫 부팅 시 seed DB 복사 후 보존

버그 수정 2건

1. OAuth state 쿠키 vs JWT 세션 쿠키 이름 충돌

Starlette SessionMiddleware와 JWT 쿠키가 모두 session이라는 이름을 사용해, OAuth 콜백 이후 미들웨어가 빈 세션을 덮어쓰면서 로그인이 풀리는 현상. 미들웨어 쿠키를 oauth_state로 개명하고 SameSite/Secure 플래그를 환경 변수로 통일했다.

2. 크로스 사이트 쿠키 차단 (Chrome 서드파티 정책)

백엔드(chaekmate-api.fly.dev)가 프론트(chaekmate.vercel.app)와 다른 도메인이라 Chrome이 세션 쿠키를 차단. Next.js rewrites를 추가해 /api/* 요청이 프론트와 같은 출처로 보이도록 프록시 처리했다.

3. 로그아웃 Set-Cookie 헤더 누락

response 파라미터를 변경하고 새로운 Response(status_code=204)를 반환해 Set-Cookie 삭제 헤더가 드랍되던 문제. 먼저 Response 객체를 생성하고 거기에 쿠키를 적용한 뒤 동일 인스턴스를 반환하도록 수정했다.


레거시 처리

Streamlit app.pyscripts/streamlit_app.py로 이동해 유지보수 모드로 전환했다. src/ import 경로는 sys.path.insert로 유지해 기존 스크립트가 깨지지 않도록 했다.


내일 할 일 (v2 잔여)


repo: sigolyori/chaekmate