a6f0774, 2026-05-09)로 main 복원사용자가 원한 것: 디테일·인터랙션 100% 유지 + 새 기능을 layer로 얹기
실제 진행된 것: 큰 파일 분리(refactor) + 새 기능 + 일부 디테일 손실
결과: 익숙한 UI 디테일·인터랙션이 미세하게 깨지면서 "작동이 안 된다"는 체감 → 폐기
| 항목 | v0.8.1 (a6f0774, 2026-05-09) | v2.0 (fba31fb, 2026-05-12) |
|---|---|---|
| 다이어리 Today | 단일 파일 621줄, swipe picker + 일정 3일치 + 루틴 + 헬스(수면·컨디션·커피·운동) + 감정 + Memo + Daily Review 5칸 + Chat topics | 5개 분리 컴포넌트 (DateSelector / ScheduleSection / RoutineSection / HealthInput / MemoSection). 일부 디테일·인터랙션 차이 |
| 다이어리 Week | 단일 441줄, 풀 통계 + 차트 + AI Report + 회고 | 6개 컴포넌트 분리 + TimeNav 추가. 차트·통계 복원됐으나 시각·인터랙션 약간 다름 |
| 다이어리 Month | 단일 478줄, 3개 차트 + 호버/터치 인터랙션 + 통계 + AI Report | 5개 컴포넌트 + CalendarGrid 흰 배경 새 디자인 + 회고 색상 도트 + ReviewModal |
| /haru | 단일 467줄, 채팅 + 키워드 자동저장 + Health/Emotion pill | 64줄 + hooks(useChatMessages, useAutoSave) + components(ChatMessage, ChatInput) + lib(keywords, markdown) |
| /friends | 모미·마음 분기 채팅 (349줄) | 삭제 (deprecate) |
| /settings 문구 | "친구들(모미/마음) AI 대화" | "하루(어시스턴트) 대화" |
| BottomNav 순서 | 홈 / 하루 / 기록 / 설정 | 홈 / 기록 / 하루 / 설정 |
| 인프라 | React Query 없음, 단순 useState+fetch | React Query 5 + vitest + Testing Library + 분리 hooks |
| 스타일 | 100% inline style={{}} | inline + 일부 Tailwind 클래스 혼용 |
| 코드베이스 | 단일 거대 파일 패턴 | 작은 컴포넌트 분리 패턴 |
증상: 사용자가 "Week/Month의 정보 부분이 안 만들어진 거야?", "month의 데이터들이 보여주는 3가지 데이터 그래프도 독립적으로 유지" 지적.
원인: Plan 작성 시 "TodayTab/WeekTab/MonthTab → 각 ~120줄 분리"라는 라인 수 목표만 챙기고, 옮겨야 할 모든 영역을 명세하지 않음.
책임: Plan 작성자(저). Plan 5(Diary Stats Restore)로 후속 복원했으나 한 라운드 추가 + 디테일 손실 잔재.
증상: 사용자가 "지금처럼 날짜 탭이 스크롤되는게 어딨어??? 이런 아님."
원인: 1203e05 원본 패턴은 가운데 박스 고정 + 날짜들이 좌우 스와이프로 들어옴 (scroll handler + centeredIndex). 새 DateSelector(Plan 2)는 scrollIntoView + opacity fade만으로 시도 — 패턴 자체가 다름.
책임: SPEC §2.2 Today selector 항목에 "정중앙 정렬 + 양옆 fade"만 적었지 기존 인터랙션 패턴(scroll handler 기반 picker)을 명시 안 함. 시안에서는 정적 이미지로 표현 → 인터랙션 차이가 시안 검토로 잡히지 않음.
증상: "하루도 지금 작동을 안 해요. 또 하루의 입력 창도 위치가 안 맞습니다."
원인 1 (자동 조정 잔재): Plan 3 subagent가 useChatMessages hook 만들 때 saveChatMessage 인자 순서를 실제 api 시그니처에 맞춤 + DB message 컬럼 → text 매핑 추가. 합리적 자동 조정이지만 1203e05 원본의 직접 호출 패턴과 다르게 작동.
원인 2 (입력창 위치): 1203e05 입력창은 column flex의 마지막 element + flexShrink: 0. 분리 버전(ChatInput)도 같은 패턴이지만 layout.tsx의 paddingBottom: 70px와 만나면 미세한 차이 발생. iPhone 13 safe-area-inset-bottom 고려가 명시되지 않음.
원인 3 (별개 환경 이슈): .env.local에 OPENAI_API_KEY 없음 + Vercel env에도 없음. 사용자가 production에서 작동했던 건 localStorage 키 덕분. v2.0과 무관한 환경 설정 문제지만 같은 시기에 발견되어 v2.0이 원인처럼 보임.
증상: 사용자가 localhost:3001에서 "안 됨"이라 보고 → 디버깅 시간 낭비.
원인:
app/ (main 브랜치) — 1203e05 복원판 + fix들 pushapp-stage9/ worktree (plan-5 브랜치) — 분리 버전, /haru 작동 안 함같은 commit이 떠 있다고 가정하고 진단 → "왜 안 되지?" 한참 헤맴. 환경 격리를 처음부터 명확히 안 알림.
증상: 시안 17_final-design-spec.html은 OK 받음 → 코드 구현 후 작동 차이 발견.
원인: 시안은 정적 mockup. 가운데 박스 고정 vs scrollIntoView는 그림으로는 같아 보임 — 실제 만져봐야 차이 인지. 시안 OK = 디자인 OK이지 인터랙션 OK가 아님.
증상: subagent 보고에 "Plan 대비 자동 조정 5건" — 합리적으로 보이는 보고서지만 그 자동 조정들이 사용자 체감 차이를 만듦.
예시:
getYearWeek 공식 — plan 안에서 자기모순 → 테스트 기준으로 수정 (잘한 일)vitest.config.ts → .mts — ESM 호환 (필요한 일)useChatMessages race condition fix — 작동에 필요 (그러나 1203e05엔 없던 race가 분리로 인해 생긴 것)vi.stubEnv 사용 — Node v22 호환 (테스트 인프라)자동 조정 자체는 합리적이지만, 누적되면 "원본과 미세하게 다른 동작"이 됨. 각 조정은 plan 명시 허용 범위 안이라 사용자 검토 게이트를 통과.
증상: SPEC 영역 5(아키텍처)에서 "큰 파일 4개 분리"를 P0(반드시)로 분류. 사용자는 "P0+P1 모두 채택"으로 동의.
원인: 사용자가 "분리해도 사용성·인터랙션 100% 동일"이라고 믿고 OK. Claude도 그렇게 약속함. 그러나 실제로는:
SPEC §6 "기존 사용자 데이터 무손상" 보장은 했지만 "사용자 체감 동작 무손상" 보장은 명시하지 않음.
| 단계 | 시각 | 결정 | 사후 평가 |
|---|---|---|---|
| Brainstorming 16 mockup | 16:00 ~ 17:00 | 시각 자료로 합의 | ✓ 좋음 — 사용자 검토 게이트 잘 작동 |
| SPEC.md 작성 | 17:00 ~ 17:30 | 10절 분량, 영역별 결정 | ! 코드 분리 범위가 너무 광범위. 사용자가 모든 디테일까지 검토 못 했음 |
| Plan 1~4 작성 | 17:30 ~ 19:00 | 4 plan, 150 step | ! Plan 2의 WeekTab/MonthTab Task에 옮겨야 할 영역 명세 누락 |
| 4 plan subagent 위임 | 19:00 ~ 21:30 | git worktree 격리 + plan별 검증 | ! Vercel preview URL로 검증했지만 사용자가 인터랙션 디테일까지 만져보기엔 시간 부족 |
| main 머지 | 21:36 | 일괄 merge | ✗ 합쳐서 한 번에 머지하기 전에 사용자가 충분히 사용했어야 함 |
| 사용자가 dev 서버에서 작동 확인 | 22:00 ~ 23:00 | "Week/Month 누락, /haru 작동 안 함" 발견 | ✗ 머지 후 발견 — 검증 게이트가 부족 |
| 부분 fix 시도 (Plan 5 + hot-fix) | 23:00 ~ 새벽 1:00 | 차트 복원 + DateSelector 재작성 + /haru 부분 fix | ✗ 누적 수정으로 사용자 인내심 소진. 작은 fix가 또 다른 차이를 만듦 |
| v0.8.1로 완전 롤백 | 새벽 1:30 | 안전 commit으로 복원 | ✓ 안전 — destructive force push 없이 단일 commit으로 처리 |
git read-tree --reset + 단일 commit 패턴이 가장 안전한 롤백 방식..env.local / Vercel env에 OPENAI_API_KEY 부재는 1203e05부터 있던 환경 문제 — 작업 시작 시 점검했어야.v2.0 작업 중 만든 자료 중 일부는 가치 있음. main에서는 삭제됐지만 GitHub remote의 stage-9/* 브랜치들에 보존됨:
stage-9/v0.9-release 브랜치 — v2.0 완성 코드 전부docs/brainstorming/2026-05-11_ux-improvement/)필요 시 cherry-pick으로 v0.8.1 위에 부분 적용 가능. 예: 회고 색상 시스템만 단독으로 도입.
작업 중 발견됐지만 v2.0과 무관한 환경 설정 문제. 정리:
# .env.local 현재 상태
ANTHROPIC_API_KEY=...
GOOGLE_CLIENT_ID=...
GOOGLE_CLIENT_SECRET=...
NEXTAUTH_SECRET=...
NEXTAUTH_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
NEXT_PUBLIC_SUPABASE_URL=...
# OPENAI_API_KEY=... ← 빠짐
/haru는 localStorage("openai_api_key") 또는 process.env.OPENAI_API_KEY 필요. 현재 둘 다 없으면 작동 안 함. 1203e05 / v0.8.1 시점에도 동일한 상태였음.
조치 권장:
/settings에서 사용자 key 입력 또는 .env.local에 추가OPENAI_API_KEY 추가v2.0이 폐기된 가장 큰 이유는 사용자 의도 해석 미스매치 + 분리 작업의 미세 부작용입니다. 새 기능 자체(회고 색상 시스템, 시간 네비 등)는 가치 있었지만, 그걸 위해 동반된 거대 refactor가 익숙한 UI 디테일을 미세하게 깨뜨렸고, 사용자 입장에서는 "안 된다"는 종합 체감으로 누적됐습니다.
기술적으로는 모든 작업이 plan에 따라 진행됐고 테스트도 통과했지만, 사용자 검증이 최종 판단이며 그 판단이 부정적일 때 즉시 롤백할 수 있는 안전망이 가장 중요합니다.
v0.8.1로 안전하게 복원된 현재가 적절한 결정입니다. 향후 새 작업 시 본 리포트의 6절 방지책을 적용하겠습니다.