사주 결과 (/saju/result)
사주 입력 후 결과를 보여주는 화면입니다. 보호 서비스에서 /saju를 거쳐 들어온 경우에는 결과 조회 후 원래 서비스로 복귀하는 중간 지점 역할도 합니다.
관련 경로
app/(main)/saju/result/page.tsx
widgets/saju-result/
features/saju-result/
├── hooks/ ← 결과 조회, 캐시, 재시도 정책
├── model/ ← API 응답 매핑
└── ui/
├── analysis-pending-gate.client.tsx ← 분석 대기 중 게이트
├── rewarded-result-gate.client.tsx ← 광고 시청 후 결과 공개 게이트
├── auth-refresh-retry.client.tsx ← 인증 토큰 갱신 후 자동 재시도
└── saju-element-animation.tsx ← 오행 애니메이션 컴포넌트
entities/saju/
shared/lib/react-query/
app/api/saju/result/route.ts
결과 조회 흐름
/saju/result 진입
│
├── 로그인 + 서버 저장된 사주 → POST /api/saju/result → 결과 렌더링
│
└── 미로그인 draft → localStorage에서 draft 읽기 → 결과 렌더링
로그인 사용자의 첫 결과 생성은 /api/saju/result에서 먼저 오늘 결과 조회를 시도합니다.
POST /api/saju/result
│
├── 기존 결과 있음 → 그대로 응답
├── 첫 결과 생성 필요 + 요청 body 있음 → body 기반으로 최초 생성
└── 첫 결과 생성 필요 + body 없음 → pending form cookie 복구 시도
PENDING_FORM_NOT_FOUND 같은 백엔드 에러 코드는 클라이언트에 raw 영어 문구로 직접 노출하지 않습니다.
복귀 흐름
/saju/result는next검색 파라미터가 있으면 결과 조회 후 원래 목적지로 복귀시킵니다.next가 없으면 결과 화면에 머뭅니다.- 보호 서비스 재진입 루프를 막기 위해 사주 입력 성공 직후 관련 프로필 캐시를 갱신하거나 제거해야 합니다.
- Turnstile 검증 쿠키가 만료된 상태에서
/api/saju/result호출이TURNSTILE_REQUIRED를 반환하면, 사주 입력 feature는 draft를 저장한 뒤/verify?returnTo=/saju/result...로 복구시킵니다. - 재검증이 끝나면 pending form cookie를 사용해 기존 제출 흐름을 이어갑니다.
캐시 정책
결과 조회는 React Query로 관리합니다. cache key와 stale/cache 정책은 features/saju-result/hooks에서 통일합니다.
상태 처리
결과 화면에는 3가지 상태가 필요합니다.
| 상태 | 처리 |
|---|---|
| 로딩 | 스켈레톤 or 로딩 인디케이터 |
| 에러 | 에러 메시지 + 재시도 버튼 |
| 빈 결과 | 안내 UI |
체크리스트
- 서버 결과인지 로컬 draft 결과인지 구분했는가
- React Query cache key가 기존 정책과 일치하는가
- 오류·로딩·빈 상태 UI가 있는가
- 백엔드 에러 코드가 사용자 문구로 매핑되는지 확인했는가
next가 있을 때 결과 조회 후 목적지 복귀가 끊기지 않는지 확인했는가- draft 흐름 변경 시
/saju·/mypage영향도 함께 확인했는가