사주 입력 (/saju)
사주 정보를 입력하는 단일 온보딩 진입점입니다. 로그인 여부에 따라 서버 저장과 임시저장(draft) 경로가 나뉘며, 보호 서비스에서 들어온 사용자는 입력 완료 후 원래 목적지로 복귀합니다.
관련 경로
app/(main)/saju/page.tsx
widgets/saju-input/
features/saju-input/
├── hooks/ ← 폼 상태, 스텝, 검증, 제출 로직
├── model/ ← 응답 가공, 파생 계산
├── type/
├── form/client/ ← 폼 UI (클라이언트 컴포넌트)
└── step/ ← 스텝별 UI
entities/saju/
app/api/saju/route.ts
app/api/saju/draft/route.ts
입력 흐름
/saju 진입
│
├── 로그인 상태 → POST /api/saju → 저장 후 /saju/result 이동
│
└── 미로그인 → POST /api/saju/draft → localStorage 임시저장
→ 로그인 후 draft 복원 → 서버 저장
보호 서비스 진입 흐름
사주 기본정보가 필요한 서비스는 /mypage/saju-manage로 보내지 않고 /saju 입력으로 진입을 통일합니다.
/compatibility | /community | /food | /mypage/traditional-fortune 진입
│
├── 로그인 + 사주 기본정보 있음 → 원래 서비스 진입
├── 로그인 + 사주 기본정보 없음 → /saju?next=...&forceInput=1
└── 비로그인 → /login?next=원래 서비스
/saju 입력 완료
│
├── next 없음 → /saju/result
└── next 있음 → /saju/result 경유 후 원래 서비스 복귀
폼 구조
사주 입력은 스텝 기반 폼입니다. 스텝 상태, 검증, 제출은 모두 features/saju-input/hooks에서 관리합니다.
// ✅ 올바른 구조
// hooks/useSajuInputForm.ts → 상태·검증·제출
// form/client/ → props 기반 렌더링만
// page.tsx → 위젯 조립
시간 입력 규칙
- 폼 계약은
birthTime: string을 유지합니다. - 화면에서는
출생 시간과출생 분을 분리 선택합니다. - 시간 옵션은
shared의HOUR_OPTIONS,MINUTE_OPTIONS를 재사용합니다. - 시간과 분을 모두 선택하면
HH:MM으로 조합합니다. 시간 미상이면birthTime은 빈 문자열로 저장합니다.- 시간 또는 분 한쪽만 선택하는 부분 입력은 허용하지 않습니다.
체크리스트
작업 전 확인 사항:
- 서버 제출인지 로컬 draft 저장인지 구분했는가
/saju/result로 넘어가는 데이터 전달 방식을 확인했는가next,forceInput검색 파라미터를 유지해야 하는 흐름인지 확인했는가- 인증 쿠키(
saju_access_token) 요구 여부를 확인했는가 - 로그인 첫 제출에서 pending cookie가 없어도 제출 body로 복구 가능한지 확인했는가
- API 응답 가공을 UI 컴포넌트에 직접 넣지 않았는가