061_LifeOS/app (Next.js 16.2.4, React 19.2.4, Tailwind 4, Supabase, NextAuth)log.mdwriting-plans 스킬로 구현 계획서 작성본 문서는 brainstorming 단계의 최종 결정사항을 한 곳에 정리한 spec입니다. writing-plans는 본 문서를 입력으로 받아 구현 단계별 plan을 만듭니다.
다음 5개 영역의 사용성 + 코드 구조를 재정비합니다:
| 항목 | 결정 |
|---|---|
/friends 라우트 | 제거 (deprecate) — /haru와 거의 동일 코드, 진입로 없음 |
| BottomNav 탭 순서 | 홈 / 하루 / 기록 / 설정 → 홈 / 기록 / 하루 / 설정 |
| 4탭 큰 구조 | 유지 |
| 페이지 입구 일관성 | 별도 변경 불필요 |
영향 파일: src/app/friends/page.tsx (삭제), src/components/BottomNav.tsx (배열 순서)
시간 네비 — 공통 패턴
‹ 라벨 › 단순 화살표 형식Today 탭
scrollLeft = (selectedIndex × ITEM_WIDTH) - (containerWidth/2 - ITEM_WIDTH/2))#000 → #DC2626 (한국 캘린더 컨벤션)Week 탭
‹ 2026-W19 · 5/10~5/16 › 시간 네비 추가getWeekRange() 함수를 인자 받도록 리팩터 (현재 주 외 임의 주차 계산)Month 탭
‹ 2026년 5월 › 시간 네비 추가| 회고 단위 | 대기 | 완료 | 표시 |
|---|---|---|---|
| 일별 (데일리 리뷰) | (표시 없음) | 🟢 초록 도트 #16a34a | 평일 셀 우하단 |
| 주별 (주간회고) | 🔴 빨간 도트 #DC2626 | 🔵 파란 도트 #2563eb | 일요일 셀 우하단 |
| 월별 (월간회고) | 핑크 배경 #fef2f2 + 月 | 셀 전체 초록 채움 #16a34a | 월말 셀 |
월간회고 trigger
upsertMonthlyReview로 저장회고 작성 UI
영향 파일: src/app/diary/TodayTab.tsx, WeekTab.tsx, MonthTab.tsx — 모두 분리 대상이므로 영역 5 분리와 함께 신규 컴포넌트로 이동
최종 7블록 순서 (8블록 → 7블록, WeatherHero+Greeting 압축):
| # | 블록 | 그룹 |
|---|---|---|
| 1 | WeatherHero + Greeting (압축) | 시각·인사 |
| 2 | DailyInsight | 인사이트 |
| 3 | TodayBlock | 액션 |
| 4 | TodoList (← 이전 5번) | 액션 |
| 5 | RoutineList (← 이전 4번) | 액션 |
| 6 | DynamicRecommend | 제안 |
| 7 | CollapsibleUpcoming (접힘) | 미래 |
영향 파일: src/app/page.tsx (render 순서), src/components/briefing/WeatherHero.tsx + Greeting.tsx (압축 통합 검토)
/haru/page.tsx (467줄) → 6개 책임 분리
| 책임 | 분리 후 위치 |
|---|---|
| 메시지 fetch/save 상태 | hooks/useChatMessages.ts |
| 키워드 감지 (운동·수면·커피·감정) | lib/chat/keywords.ts |
자동 저장 로직 (autoSaveFromChat) | hooks/useAutoSave.ts |
| 마크다운 → HTML 변환 | lib/markdown.ts |
| 메시지 한 개 렌더 | components/chat/ChatMessage.tsx |
| 입력 영역 | components/chat/ChatInput.tsx |
분리 후 haru/page.tsx는 약 80줄.
자동 저장 토스트 신설 (components/ui/Toast.tsx)
useToast 훅으로 트리거 (다른 페이지 재사용 가능)/settings/page.tsx (213줄, 양호)
P0 — 다이어리 3탭 분리
| 현재 | After |
|---|---|
TodayTab.tsx 621줄 | app/diary/TodayTab.tsx ~120줄 (탭 컨테이너) |
MonthTab.tsx 478줄 | app/diary/MonthTab.tsx ~120줄 |
WeekTab.tsx 441줄 | app/diary/WeekTab.tsx ~120줄 |
분리되어 src/components/diary/ 신설 폴더에 들어가는 컴포넌트:
DateSelector.tsx — Today의 정중앙 정렬 가로 selector (일요일 빨강 반영)HealthInput.tsx — 수면/컨디션/커피/운동 입력 (Today 공유)MemoSection.tsx — 메모·데일리 리뷰 작성WeekChart.tsx — 주차 차트CalendarGrid.tsx — Month 캘린더 (회고 색상 시스템 + 3:2 셀)TimeNav.tsx — ‹ 라벨 › 공통 시간 네비 (Today/Week/Month 모두 사용)ReviewModal.tsx — 회고 작성 Bottom sheet (components/ui/ 에 둘지는 구현 단계 결정)P0 — React Query 도입
@tanstack/react-query (~40KB gz)src/lib/supabase/queries.ts 신설 — Supabase API wrapper 훅: - useHealthLog(date), useHealthLogs(range)
- useJournalEntry(date), useJournalEntries(range)
- useRoutines(), useRoutineLogs(range)
- useChatMessages(), useWeeklyReview(week), useMonthlyReview(month)
- mutation: useUpsertHealthLog, useUpsertJournal, useSaveChatMessage, …
staleTime: 1분, gcTime: 5분, refetchOnWindowFocus: false 를 src/app/layout.tsx (또는 SessionWrapper.tsx 안)에 추가lib/supabase/api.ts 는 유지 (queries.ts가 wrapper로 사용)P1 — Tailwind 점진 마이그레이션
style={{...}}는 동시 전환하지 않음 — 영역별 작업 시 함께 변환src/styles/ (신설) + tailwind.config 확장으로 관리theme/timeColor.ts)은 CSS 변수로 노출 → Tailwind에서 var(--accent) 사용P1 — Dead code 정리
다음 파일 모두 삭제 (briefing 외 import 0회 확인됨):
src/app/friends/page.tsx (349줄)src/components/briefing/CharacterTabs.tsxsrc/components/briefing/MaeumView.tsxsrc/components/briefing/MomiView.tsx총 ~900줄 제거.
P1 — debug API routes 환경 분기
src/app/api/debug/headers/route.tssrc/app/api/debug/oauth/route.tssrc/app/api/debug/route.ts처리 방식:
if (process.env.NODE_ENV === "production") return new Response(null, { status: 401 }) 추가→ 구현 단계에서 a/b 결정. 기본 권장: a (개발 편의 유지).
P2 — 보류
tsconfig.json target ES2017 → ES2022 (후속 라운드)
src/
├── app/
│ ├── layout.tsx + QueryClientProvider 래핑
│ ├── page.tsx (홈 — 7블록 순서 반영, WeatherHero+Greeting 압축)
│ ├── diary/
│ │ ├── page.tsx (탭 라우터, ~30줄)
│ │ ├── TodayTab.tsx (~120줄, 분리)
│ │ ├── WeekTab.tsx (~120줄, 분리)
│ │ └── MonthTab.tsx (~120줄, 분리)
│ ├── haru/page.tsx (~80줄, 분리)
│ ├── settings/page.tsx (213줄, 문구만 갱신)
│ ├── (friends/ → 제거)
│ └── api/
│ ├── auth/ calendar/ chat/
│ └── debug/ (환경 분기 추가)
├── components/
│ ├── ui/ ★ NEW
│ │ ├── Toast.tsx
│ │ └── ReviewModal.tsx
│ ├── briefing/ (CharacterTabs/Maeum/Momi 제거)
│ │ └── (정리된 홈 전용 블록들)
│ ├── diary/ ★ NEW
│ │ ├── DateSelector.tsx
│ │ ├── HealthInput.tsx
│ │ ├── MemoSection.tsx
│ │ ├── WeekChart.tsx
│ │ ├── CalendarGrid.tsx
│ │ └── TimeNav.tsx
│ ├── chat/ ★ NEW
│ │ ├── ChatMessage.tsx
│ │ └── ChatInput.tsx
│ ├── BottomNav.tsx (탭 순서 변경)
│ └── SessionWrapper.tsx (QueryClientProvider 위치 검토)
├── hooks/ ★ NEW
│ ├── useChatMessages.ts
│ ├── useAutoSave.ts
│ ├── useHealthLog.ts
│ ├── useReviews.ts
│ └── useToast.ts
├── lib/
│ ├── ai/ data/ theme/ types/
│ ├── chat/ ★ NEW
│ │ └── keywords.ts
│ ├── markdown.ts ★ NEW
│ └── supabase/
│ ├── api.ts (기존 유지)
│ └── queries.ts ★ NEW (React Query wrappers)
└── styles/ ★ NEW (Tailwind 토큰 확장)
| 토큰 | 의미 | HEX |
|---|---|---|
--review-pending | 주간회고 대기 | #DC2626 |
--review-week-done | 주간회고 완료 | #2563eb |
--review-day-done | 일별 회고 완료 (도트) | #16a34a |
--review-month-done | 월간회고 완료 (셀 채움) | #16a34a |
--review-day-done과 --review-month-done은 같은 초록. 의미 단위는 다르나 시각적 통일성 우선.
src/lib/theme/tokens.ts 또는 src/styles/의 CSS 변수로 노출 권장.
기존 Supabase 스키마(getWeeklyReview, getMonthlyReview, upsertHealthLog, upsertJournalEntry)를 그대로 활용. 새 테이블/컬럼 추가 없음.
단, 회고 완료 여부 판단을 위해 다음 조건 사용:
journal_entries 또는 daily_review 필드에 내용 존재weekly_reviews 레코드 존재 + 내용 비어있지 않음monthly_reviews 레코드 존재 + 내용 비어있지 않음hooks/useReviews.ts 에서 boolean 노출. 구현 시 정확한 "완료" 기준은 writing-plans에서 확정.
| 항목 | 요구 |
|---|---|
| 사용성 | Today selector 가로 스크롤이 60fps 유지, 정중앙 정렬 부드러움 |
| 성능 | 페이지 전환 시 캐시된 데이터 즉시 표시 (React Query), 초기 로드 1.5초 이하 |
| 접근성 | 회고 도트는 색상 외에도 형태(도트/체크) 구분, 색맹 사용자도 대기/완료 구분 가능. 추후 hover/focus 시 텍스트 라벨 노출 |
| 보안 | debug API routes 프로덕션 차단, API key는 password 마스킹 유지 |
| 모바일 | 회고 작성 Bottom sheet는 키보드 노출 시 자동 스크롤, 50% 화면 점유 기본 |
| 호환성 | 기존 사용자 데이터 무손상 (스키마 변경 없음) |
writing-plans 단계에서 다음 순서로 plan 분할 권장:
1차 — 토대 (1~2일)
@tanstack/react-query 설치 + QueryClientProvider + 첫 hook useHealthLog 검증)components/ui/Toast.tsx + hooks/useToast.tscomponents/diary/TimeNav.tsx (공통 컴포넌트)2차 — 다이어리 분리 (2~3일)
getWeekRange(date?) 리팩터ReviewModal.tsx + 월간회고 자동 trigger3차 — 하루 + 홈 (1~2일)
/haru 분리 (hooks 2개 + lib 2개 + components 2개)src/app/page.tsx render 순서)4차 — 정리 (1일)
/friends 삭제/settings 안내 문구 갱신각 단계는 독립적으로 PR 가능. 회귀 테스트는 매 단계 후 수동 + 자동(추가될 경우).
ReviewModal 위치: components/ui/ vs components/diary/QueryClientProvider 마운트 위치: app/layout.tsx vs SessionWrapper.tsx 안docs/design-history.html — Stage 9 추가 (5/11) ✓ + 영역 4·5 결정 반영 (예정)docs/design-evolution-report.html — v0.9 추가 (5/11) ✓ + 영역 4·5 결정 반영 (예정)docs/brainstorming/2026-05-11_ux-improvement/log.md — 시간순 진행 기록본 spec이 변경되면 위 세 문서도 동기화.
본 spec을 입력으로:
writing-plans 스킬 호출 전 사용자 spec 검토 필요.