디자인 배송 v82 — 세션 수정 복귀 오버레이 복원·시간 수정 모달·달력 하이라이트 (2026-08-29)
- 기간: 2026-08-29 (1세션, 오너 지시 "이거 디자인 반영좀 진행해줘 … 오너확인없이 끝까지 완주후 보고")
- 랜딩: PR #914(반입+배선,
2ed8c0bf) — 마이그레이션 없음, Vercel Production 배포 - 설계서: 없음(배송 반입 건) — 분석·Phase 계획 = 이슈 #909 코멘트(예상 효과·개선사항 표 포함)
- 정본:
session-screen-props.mdsessionAsOverlay 조항 ·src/react/contracts/designContract.ts마커 4종 ·src/react/mobileApp.tsxupdateUiSessionTimes - 도구: 없음
- 게이트:
tests/react/statsCentralizationPhase2.test.mjs산술 합산 앵커(스탯 3항 새 표면으로 이전, 삭제 0) · eslint-baseline 검토 억제 3건(SessionScreen 2·SessionSheetBody 1) - 버그리포트: 없음(결함 수리 아님)
- 계약: session-screen-props.md에 sessionAsOverlay 절 신설(오버레이 문법·하루 스택 복원 가드·컨테이너 의무 = 수정 복귀 시 selectedSession 유지)
Phase 현황
| Phase | 내용 | 상태 |
|---|---|---|
| Phase 1 | 반입 — verbatim 적용·헝크 감사 | ✅ PR #914 (2ed8c0bf) |
| Phase 2 | 배선 — sessionAsOverlay 공급·시간 영속화 어댑터·마커 등록 | ✅ PR #914 |
| Phase 3 | 검증 — tsc·테스트 2077·게이트 10종·CI | ✅ |
| Phase 4 | 랜딩 — 머지·Production 실측 | ✅ |
| Phase 5 | 기록 — 본 문서 + 등록 2곳 | ✅ |
1. 배경
일지·친구 달력의 세션 상세는 v80(#862)에서 하루/월 오버레이 위 3겹째 오버레이 스택 문법이 됐지만, 수정 플로우에서 돌아오면 구형 풀페이지 분기(selectedSession && !anySheet)로 떨어져 원래 보던 스택(하루 상세→세션 상세)이 사라졌다. 또 세션의 시작·종료 시간은 표시만 있고 수정 수단이 없었다. 디자인 환경이 delivery-20260829(v82)로 이 두 흐름과 달력 하이라이트(완료일·오늘)를 재설계해 배송했다.
2. 문제 제기
수정 복귀가 문맥을 잃는다
수정 저장/취소 후 세션 상세가 오버레이 스택으로 복원되지 않고, 재마운트마다 진입 슬라이드가 다시 재생됐다(제자리 복원이 아니라 "새로 열림"처럼 보임).
운동 시간을 고칠 수 없다
completedSessionWriteProjection은 startTime/endTime/duration을 이미 실어 나르는데(기존 수정 경로), UI에 시간 수정 표면이 없었다. 컨테이너의 updateUiSession(sessionId, next)는 UI 호출 지점 0곳인 휴면 경로였다.
3. 해결 방안
원칙
- 배송 계약 v2(manifest·hunkAudit) + 수신 측 교집합 직접 실측(신고 불신 — v81 교훈).
- 표면이 사라져도 계약은 살아 있는 표면으로 앵커 이전(삭제 0 — v81 교훈).
- 어댑터 패치는 시간 필드로 한정 — 세션 본문 왕복은 updateUiSession의 authoritative 재조회(ensureSessionDetail force)에 맡긴다(전체 세션 객체를 패치로 흘리면 stale exercises가 쓰기 투영에 들어갈 수 있음).
접근
| 대안 | 판정 |
|---|---|
UI가 2-인자 (sessionId, patch)로 직접 호출하게 배송 코드 수정 | 기각 — 배송 파일 verbatim 원칙, 디자인 소유 코드 재작성 금지 |
컨테이너 어댑터 updateUiSessionTimes(1-인자 수용 + duration 재계산) | 채택 — duration 재계산은 컨테이너 소유(manifest 명시)와 일치 |
| 일지 탭 sessionAsOverlay 무조건 true | 기각 — PR 점프(종목 페이지→세션)의 "돌아가기" 풀페이지 바·하이라이트가 오버레이 스택에 없음 → {!prJump} 조건 공급 |
4. 적용한 내용
Phase 1 — 반입 (PR #914 커밋 1)
SessionScreen.tsx(sessionAsOverlay·하루 스택 복원·restoreQuiet/오버레이별 quiet 캡처·fc-cell done) · SessionSheetBody.tsx(스탯 3항·시간 수정 모달 sessionTimeDialog·문서+연필 아이콘) · primitives(pg-restore)/overlays(ss-tm-* 계열)/session(오늘 필 원·완료 잉크)/day-summary css · session-screen-props.md. base fc9f82f0 = origin/main 조상 확인, 교집합(base..main ∩ changedFiles) 0 실측, 헝크 감사 manifest hunkAudit 1:1·stale-revert 0·오염 grep 0.
Phase 2 — 배선 (PR #914 커밋 2)
- mobileApp: 일지 탭
sessionAsOverlay={!prJump}· 친구 스코프 달력sessionAsOverlay· 모바일 onUpdateSession 5지점 전부updateUiSessionTimes로 교체(그룹 멤버 세션·일 요약 레이어는 미공급 현행 유지). updateUiSessionTimes:HH:MM파싱 → 분 차(자정 넘김 wrap) →durationLabelFromMinutes— duration·durationLabel 동시 갱신.- designContract:
session.detail.editTime·session.time.save·session.time.cancel·sessionTimeDialog등록. - statsCentralizationPhase2 산술 합산 단언을 스탯 3항 새 표면으로 이전(총 무게·세트 수(+랩)).
주요 결정과 그 근거
sessionAsOverlay={!prJump}: 배송의 풀페이지 게이트가!sessionAsOverlay를 포함해, 무조건 공급하면 PR 점프 복귀 바("종목 페이지로 돌아가기")·highlightExerciseId가 사라진다. 조회+복귀 문맥은 계약문의 "조회 문맥 풀페이지"에 해당.- 수정 복귀 selectedSession 유지 의무: 기존 edit-save 경로가
setSelectedSession(confirmedSession)으로 이미 이행 — 컨테이너 무변경으로 충족 확인.
작업 중 드러난 것
- 다중행 effect의 exhaustive-deps는 deps 배열 행에 보고된다 —
eslint-disable-next-line을 훅 호출 위에 두면 unused-directive로 오히려 에러(억제는 deps 행 바로 위에). 단일행 effect는 호출 행 억제로 충분. - 로컬 eslint 실행 불가(@babel/core 부재) — exhaustive-deps 판정은 CI가 유일. CI 1차 RED(4건) → 검토 억제 + eslint-baseline suppressionsByFile 등록 2단으로 수리.
- 작업 중 main 3회 전진(#908·#911·docs, mobileApp.tsx 포함) — 리베이스 후 tsc·전체 테스트 재실행으로 재검증(v80 교훈 재실전).
- 배송의 스탯 라벨 개편("볼륨"→"총 무게")이 statsCentralizationPhase2 앵커를 깼다 — 새 표면 이전으로 계약 유지.
5. 적용 결과
| 항목 | 결과 |
|---|---|
| 수정 복귀 | 달력 랜딩/풀페이지 → 원래 오버레이 스택(하루 상세 층 포함) 복원 + 진입 애니 억제(pg-restore) — 디자인 하니스 실렌더 확인, 오너 실기기 미검증 |
| 시간 수정 | 불가 → 모달 수정·저장(기존 세션 수정 RPC 재사용)·duration 라벨 재계산 — 실기기/Production 저장 왕복 미검증 |
| 세션 상세 스탯 | 4항 → 하루 상세 동일 3항(총 무게·운동 시간·세트 수(+랩)) |
| 일지 달력 | 완료일 액센트 잉크 14px/800 · 오늘 액센트 필 원+흰 숫자 — Production 청크 실측 |
| 검증 | tsc 0 · 테스트 2077/2077 · 게이트 10종 green · CI verify pass(3m53s) · Vercel Production 배포 |
6. 이번 개선으로 향상된 것
수정 흐름이 문맥을 보존한다
일지에서 세션을 고치고 돌아와도 보던 자리(하루 상세→세션 상세 스택)가 그대로 — v80 오버레이 문법의 마지막 구멍이 닫혔다.
운동 시간이 사용자 소유가 됐다
잘못 기록된 시작~종료를 앱 안에서 수정 가능. 저장 경로는 기존 수정 RPC 재사용이라 서버 신설 0.
구조적으로 남는 것
session-screen-props.md sessionAsOverlay 조항(컨테이너 의무 명문화) · designContract 마커 4종 · 산술 합산 앵커의 새 표면 단언 · eslint 억제 위치 규칙(다중행 effect = deps 행).
남은 것
- 오너 실기기 확인(수정 복귀 스택·시간 모달 저장·달력 하이라이트) — 이슈 #909 [확인대기].
- manifest 이월 ⑤: report byFunc sets 공급 · 컨테이너 오버레이 스와이프 뒤로가기(⑧) · UiDaySummary 폐기 판단(⑨) — delivery-20260827b manifest 참조.
- 시간 검증 규칙(시작>종료 서버 거부 등) 미신설 — 기존 수정 경로와 동일 수준(클라 wrap 계산만).