사주고사 제작기 13. 캐릭터 50개 확정, 사주 해석 사전 생성 완료, UX 개선
캐릭터를 50개로 확정·정리하고, 사주 해석 사전 생성을 완료하고, 에세이 타이핑/스크롤/모바일 UX를 소폭 다듬었다.
1. 캐릭터 50개 확정 + 사전 생성 완료
배경
12일차 끝에 80개까지 늘렸다가 다시 50개로 좁혔다. 이유는 단순하다.
- 사주 해석 사전 생성 비용: 80개 × Gemini API = 수십 번 호출, 일일 한도(20req/day) 한계로 4일 이상 소요 예상
- 콘텐츠 품질 vs 볼륨 트레이드오프: 80개를 채우면서 캐릭터 서사의 밀도가 떨어졌다. 50개를 정밀하게 만드는 쪽이 낫다고 판단
pnpm generate:saju를 재실행해 c44~c50까지 추가 생성, 총 50개 완료.
c51~c80 삭제
삭제 파일:
- detective-scenarios-batch12.ts ~ batch18.ts (7개)
- batch11.ts → c49~c50만 남기고 재생성
- detective-scenarios.ts의 import 정리
- generated-questions.json에서 c51~c80 항목 제거총 ~4000줄 삭제. 번들 크기도 함께 감소.
resume-safe 스크립트의 가치
generate-detective-saju.ts는 매 캐릭터 생성 후 즉시 JSON 파일에 저장하도록 설계되어 있다. 덕분에 일일 한도로 중단되어도 pnpm generate:saju 재실행 한 번으로 이어서 생성 가능했다. 중단-재개 패턴은 이런 배치 작업에서 필수다.
2. 내 사주보기 AI 해석 — 냉정·솔직 풀이로 개선
문제
lib/gemini-saju.ts의 기존 프롬프트는 "종합적인 해석을 제공하세요" 수준이었다. 결과물이 "좋은 에너지를 가지고 있습니다", "대인관계가 원만합니다" 같은 긍정 편향 문장으로 가득 찼다. 사주 앱의 진지함을 해치는 요소였다.
프롬프트 원칙 강화
추가한 지시문 (요약):
- 약점·단점·불리한 구조를 장점만큼 충분히 언급
- 막연한 위로 대신 구체적인 리스크 명시
- "~할 수 있습니다" 식의 애매한 표현 지양
- 상충하는 오행 조합은 내면 갈등으로 직접 서술변경 전후 체감 차이가 크다. "재물운이 있습니다" → "금(金)이 과다해 욕심이 앞설 때 오히려 손재수가 생깁니다" 수준의 구체성으로 바뀌었다.
3. UX 개선 3종
결과 화면 스크롤 최상단 이동
추리 모드에서 결과 화면으로 전환될 때 스크롤 위치가 유지되어, 게임 중 스크롤을 내려뒀으면 결과 화면이 중간부터 보이는 문제가 있었다.
// detective-client.tsx — finished 상태 진입 시
useEffect(() => {
if (gameState.phase === "finished") {
window.scrollTo(0, 0);
}
}, [gameState.phase]);공유 결과 페이지(/detective/result/[resultId])는 서버 컴포넌트라 useEffect를 쓸 수 없어 ScrollToTop 클라이언트 컴포넌트를 별도로 만들어 마운트 시 실행하도록 했다.
에세이 타이핑 성능 개선
에세이 입력 창에서 타이핑 시 렉이 발생했다. 두 가지 원인:
① backdrop-blur-sm 제거
quiz-client.tsx의 sticky 헤더에 backdrop-blur-sm이 붙어 있었다. blur는 GPU 합성 레이어를 생성하고, 텍스트가 긴 textarea 위에서 스크롤/타이핑마다 리페인트를 유발한다. 모바일에서 특히 심했다. 단순 삭제로 해결.
② useDeferredValue 범위 확장
기존에는 essay 값에만 deferred를 적용했는데, 글자 수 카운터(charCount)도 함께 지연 처리해 입력 직후 React 렌더 부담을 줄였다.
// 변경 전
const deferredEssay = useDeferredValue(essay);
// 변경 후
const deferredEssay = useDeferredValue(essay);
const deferredCharCount = useDeferredValue(essay.length); // 카운터도 지연모바일 에세이 progress bar 숨김
에세이 작성 화면 상단의 progress bar가 모바일에서 불필요하게 공간을 차지하고 있었다. 에세이 모드는 1문제 단일 화면이므로 progress 표시 자체가 의미없다. hidden sm:block 처리로 모바일에서 숨김.
4. CLAUDE.md → docs/rules/ 분리
CLAUDE.md가 300줄을 넘어가면서 AI 컨텍스트 로딩 효율이 낮아졌다. 내용을 주제별로 분리했다:
CLAUDE.md (8줄 — @import 참조만)
└── docs/rules/overview.md # 기획/기술스택/결정사항
└── docs/rules/structure.md # 파일 구조 트리
└── docs/rules/data-security.md # DB/보안 설정
└── docs/rules/status.md # 완료/미구현 현황Claude Code는 @파일명 형태의 import를 지원하므로 CLAUDE.md에서 각 파일을 참조하면 자동으로 로딩된다. 파일이 작을수록 필요한 섹션만 읽을 수 있어 토큰 효율이 높아진다.
5. 배운 것
- 볼륨보다 완성도: 80개에서 50개로 줄인 결정이 옳았다. 사전 생성 완료가 가능해졌고, 콘텐츠 품질도 올라갔다.
- backdrop-blur는 공짜가 아니다: 긴 텍스트 레이어 위에서 blur는 GPU 합성 비용을 크게 올린다. 장식 목적이라면 과감히 빼는 게 낫다.
- 프롬프트 편향은 명시적으로 막아야 한다: LLM은 기본적으로 긍정 편향이 있다. "약점도 충분히 언급하라"는 지시를 넣지 않으면 항상 좋은 말만 한다.
- 문서도 코드처럼 리팩토링한다: CLAUDE.md를 나눈 건 단순한 파일 분리가 아니라, AI가 읽는 컨텍스트의 신호 대 잡음비를 높이는 작업이다.
남은 과제
- generated 문제(96개) analysis 만세력 + 평생 사주풀이로 보강
- 문제/인물 데이터 Supabase 이관
- Rate limiter 영구 저장소 전환 (Upstash Redis 등)
exclude파라미터 localStorage 연동
커밋 로그
24a1da7 feat: 내 사주보기 AI 해석을 냉정·솔직 풀이로 변경
33749ce chore: 사주 해석 사전 생성 45개로 확장 (c1~c43, c51, c73)
617b2fc chore: 사주 해석 사전 생성 49개로 확장 (c44~c47 추가)
ba22721 refactor: 캐릭터 50개로 정리 + 사주 해석 사전 생성 완료
a3ebab5 docs: CLAUDE.md 기획 업데이트 — 먹 테마, 50개 캐릭터, UX 개선 반영
62e06fa fix: 결과 화면 스크롤 최상단 이동 + 에세이 타이핑 성능 개선
a8fb4e8 docs: CLAUDE.md를 docs/rules/로 분리하여 경량화
77d1c00 fix: 모바일에서 에세이 프로그래스바 숨김 처리