Skip to content

하루 상세 재설계 — 타임 레일에서 세션 카드·3항 요약으로, 그리고 배송 되덮기 감사 (2026-08-27)

  • 기간: 2026-08-27 (1세션, 오너 지시 원문: "새 디자인 반영좀 해줘 PR 생성하고 머지까지" — 배송 세션 디자인 요청 (3).zip = delivery-20260827b)
  • 랜딩: PR #881 (반입·배선, 00066d5c) · PR #883 (표시 표면 축소, c6657484) — 둘 다 Vercel Production success 실측(아래 5절 청크 마커 표), 마이그레이션·엣지 함수 없음
  • 설계서: 없음(디자인 배송 반입) — 배송 정본 = src/react/ui/CHANGE-NOTES.md 13항목 + src/react/ui/delivery-manifest.json(hunkAudit 65헝크)
  • 정본: src/react/ui/mobile/lib/DayDetailBody.tsx(3항 스탯박스·세션 카드·formatSetRuns 축약) · src/react/ui/mobile/styles/base/tokens.css(--tabbar-h) · src/react/ui/mobile/screens/ProfileScreen.tsx(UiCustomExercisesScreen) · src/react/contracts/designContract.ts(마커 장부)
  • 도구: Production read-only 청크 프로브(curl → mobileRoot-*.css·group-*.css·profile-*.css·ProfileScreen-*.js 마커 계수)
  • 게이트: tests/react/dockGeometryContract.test.mjs(탭바 토큰 55) · designContract.test.mjs(마커 장부 양방향) · customExerciseArchiveUi.test.mjs(독립 화면 렌더) · calendarExactSummaryProjection·statsCentralizationPhase1·clientStrengthFallback·dayTopSetsEffectiveLoad·mobilePostSaveReadModelRegression(3항 요약·축약 표기 앵커)
  • 버그리포트: 없음 — 되덮기 2건은 머지 전 감사에서 차단(Production 무영향)
  • 계약: docs/contracts/day-summary-props.md·report-props.md·profile-screen-props.md·shell-frames.md 개정 · group-props.md는 main 정본 위에 스와이프 뒤로가기 전환 규칙 표만 추가

1. 배경

08-27 오전에 v80 반입(#862)과 화이트보드 수리(#876)가 연달아 랜딩했고, 같은 날 오후 오너가 다음 디자인 배송(delivery-20260827b)을 그대로 반영해 머지까지 요청했다. 배송 범위는 하루/주/월 상세 전면 재설계, 일지·그룹 오버레이 내비 정돈, 커스텀 종목 관리 화면 분리, 탭바 높이 하향 — 화면 14파일 + 계약문 5 + 신설 CSS 1.

배송 manifest는 스스로 "08-27 02:56Z 재싱크 이후 main이 #875 Phase 1·2로 전진했고 GroupScreen·group.css는 rebase했다"고 신고했다. 즉 패키저가 이미 상류 전진을 알고 있었다 — 문제는 그 인지가 두 파일에만 적용됐다는 점이다.

2. 문제 제기

배송 zip이 상류 수리 2건을 조용히 되돌리는 상태였다

manifest의 changedFiles(14) ∩ (v80 랜딩 639cf234 이후 main 전진분)을 직접 교집합 검사한 결과 5파일이 겹쳤고, 그중 2건이 되덮기였다:

파일상류zip 상태
styles/screens/session.css#872 fc-mbtn { color: var(--ink) } (iOS 기본 버튼 파랑 수리)그 1줄이 없는 판 → 머지 시 iOS 월 타이틀 파랑 재발
docs/contracts/group-props.md#876 gpDoneByMember 사람 단위 완료 조항 3불렛조항 없는 낡은 판 + 오타 오염("나눔스퀘어라운드" → "나눔스쿠어라운드")

manifest가 rebase했다고 신고한 GroupScreen.tsx·group.css는 실제로 상류 심볼(gpDoneByMember·GbSkeletonRows·gb-skel)이 보존돼 있었다. 되덮기는 패키저가 교집합이 없다고 판단한 나머지 파일에서 나왔다 — 신고를 믿고 그 두 파일만 검사했으면 둘 다 통과했다.

재설계가 기존 계약 테스트 15건의 전제를 깨뜨렸다

요약이 8항 → 3항으로 줄고 소제목·가로선·"최고 강도" KPI가 은퇴하면서, 그 텍스트를 앵커로 쓰던 테스트가 무더기로 깨졌다. 표면이 사라진 것이지 계약이 사라진 게 아니라 — 예를 들어 "프로젝션 없는 세트는 로컬 추정을 하지 않는다"는 계약은 살아 있는데 그것을 읽던 <b>—</b><i>최고 강도</i> 앵커만 없어졌다 — 앵커를 옮길지 계약을 놓을지 한 건씩 판정이 필요했다.

관리 진입로가 소멸할 뻔했다

배송은 커스텀 종목 카드를 내 정보에서 삭제하고 독립 화면 UiCustomExercisesScreen을 신설했지만, 드로어 → 화면 배선은 "Codex 후속"으로 미뤘다. 반입만 하면 앱에서 커스텀 종목 관리로 가는 길이 아예 없어진다.

3. 해결 방안

원칙

  • D1 — 상류가 base다: 되덮기 파일은 zip을 버리고 main 원문 위에 디자인 델타만 재적용. 계약문은 main 정본에 새 절만 append.
  • D2 — 진입로 없는 화면은 반입이 아니다: manifest가 후속으로 미룬 항목 중 반입 즉시 기능이 사라지는 것(①~⑤)은 같은 PR에서 처리하고, 판단이 필요한 것(⑧⑨)만 남긴다.
  • D3 — 표면이 바뀌면 앵커를 옮기고, 계약은 그대로 잠근다: 테스트를 지우지 않고 새 표면의 등가 앵커로 이전. 등가물이 없으면(예: 종목 수 항목) "아예 안 그린다"로 뒤집어 잠근다.

접근

대안판단
zip 그대로 반입 + 되덮기는 후속 PR기각 — #872는 오너가 실기기로 보고한 수리다. 재발 후 다시 고치는 왕복이 더 비싸다
교집합 전수 검사 → 되덮기만 main 우선 복원채택 — 5파일 중 실제 되덮기 2건만 손대고 나머지 디자인 델타는 그대로
배송을 반려하고 재패키징 요청기각 — 왕복 1일. 되덮기가 2건·10줄 규모라 수신 측 복원이 싸다

4. 적용한 내용

반입 (#881)

디자인 14파일 + 계약문 5 + styles/screens/profile.css 신설. 주요 변경:

  • 하루/주/월 상세: 타임 레일 → 세션 카드(카드 전체가 세션 상세 진입 + "자세히 ›", 완료 카드 = 페리윙클 헤어라인 + 우상단 초록 체크) · 세트 표기 = 피드·화이트보드와 동일 축약(formatSetRuns, "100kg 5x3") · 요약 = 3항 스탯박스(총 무게 / 운동 시간 / 세트 수(총 랩)), 0값 상시 표기 · 날짜 헤더 = YYYY.MM.DD 요일 + 좌우 스텝퍼
  • 오버레이 내비: 일지 하루·세션 상세 = 워드마크 행 + 행내 (타 탭과 같은 y) · "세션 상세" 타이틀 행 삭제 · 상단 간격 소유자 단일화(합산 44 → 15px) · 레이어 열림 중 판 비침·safe-top 소실 수정(.tab-keep.off 예외)
  • 리포트 6각 레이더: 최대값 상대 스케일 + 세트 수 기준(sets 미공급 데이터는 share 폴백) · 레전드 ±24px · 점 r 1.8
  • 그룹 3표면 좌→우 스와이프 뒤로가기(dx>45 && |dx|>|dy| → .out 슬라이드 아웃, reduced-motion은 즉시 onBack())
  • 탭바 68 → 55(--tabbar-h 소유자 + 패딩 6/6·탭 2)
  • 세트 행 동그라미 완료에도 RPE 카드 열림(도크 FAB와 동일)

되덮기 복원

  • session.css — zip 판을 반입한 뒤 fc-mbtncolor: var(--ink) 1줄을 #872 원문 그대로 재삽입(주석 포함).
  • group-props.md — zip 판을 버리고 git checkout origin/main으로 정본 복원 후, zip이 새로 쓴 "좌→우 스와이프 뒤로가기" 절(13줄)만 append.

배선 (manifest 후속 ①~⑦·⑩)

#내용
NavDrawerProps.onCustomExercises 타입 2줄(범위 밖 필수 편집 — 없으면 type-check 실패)
드로어 → UiCustomExercisesScreen 레이어: recordsTool 유니온에 "customExercises" 추가, prTool과 동일한 lazy 레이어 문법
마커 profile.customExercises.open 부여 + 장부 등록 · daySummaryExercises 훅 소멸 반영 · data-lg-status: sync_pending 신규 등록
MOBILE_SHELL_COPY.drawer.customExercises 등재(폴백 문자열 제거)
profile.css lazy import 쌍 + 부팅 웜 목록 편입
daySummaryExercises를 읽던 테스트 2건 개정
report byFuncsets — 매퍼(mobileReportViewMappers.ts)가 이미 행마다 공급 중임을 확인, 추가 작업 없음
dockGeometryContract의 탭바 68 하드코딩 기대 → 55

추가로 loadOwnCustomExercises를 렌더 컨텍스트에 노출했다. 드로어 진입은 프로필 탭을 거치지 않아 activateForProfileTab의 1회 로드가 발화하지 않는데, 같은 idempotent 함수를 그대로 재사용해 화면 열기 시점에 목록을 적재한다(새 로더를 만들지 않았다 — 오너 변경 리셋 로직이 한 곳에만 있어야 한다).

표시 표면 축소 (#883, 반입 직후 오너 지시)

반입본을 오너가 실제로 열어 보고 곧바로 지시했다 — "지금 하루 상세에서 원 그래프랑 top 세트 나오는데, 그거 지워줄래?". 재설계가 요약을 3항으로 줄였는데 그 아래에 구 8항 시절의 분석 표면(세트 강도·목적·RPE 도넛 3종 + 탑세트 TOP 3)이 그대로 남아 있어, 하루 화면이 여전히 길었다.

도넛·탑세트 섹션에 (wk || mo) 게이트를 걸어 주/월 범위 드로어 전용으로 축소했다(범위 드로어는 분석 표면이므로 그대로 둔다). 하루 상세 = 3항 요약 + 세션 카드.

이때 드러난 것: 서버 탑세트는 exactDay = !!exactTotals && !wk && !mo 조건으로만 만들어진다. 즉 체중 태그·유효 무게 표기(오너 D1 2026-08-23)의 실제 소유자는 이제 데스크톱 일지 패널(DkJDayPanel)뿐이다. 그래서 테스트를 지우지 않고 앵커를 살아 있는 표면으로 옮겼다:

계약전 앵커후 앵커
탑세트 = 유효 무게 + 체중 태그(D1)모바일 하루 상세데스크톱 DkJDayPanel
서버 강도 % 동일성(달력/리포트 ↔ 범위)하루 도넛주 드로어 도넛(wk: true)
서버 stimulus_class만 집계(로컬 재분류 금지, D1 08-21)하루 도넛주 드로어 도넛(wk: true)
경계 세션 정확치 미제시하루 탑세트 행데스크톱 패널 + 모바일 미렌더 단언

신규 잠금 1건: "하루 상세는 탑세트·도넛을 그리지 않는다(세션 카드·3항 요약은 남는다)".

주요 결정과 그 근거

  • 테스트 15건은 앵커 이전으로 처리, 삭제 0건. "최고 강도" KPI가 사라진 자리는 탑세트 행 pct 칼럼이 같은 서버 강도를 보여주므로 그리로 옮겼고, 종목 수 항목처럼 등가물이 아예 없는 계약("경계 세션 종목 수를 정확치로 제시하지 않는다")은 doesNotMatch(/daySummaryExercises/)로 뒤집어 잠갔다.
  • dockGeometryContract 개정은 계약 개정이다. 그 파일 머리에 "단언을 끄거나 지우는 변경은 오너 결정 없이 금지"라고 적혀 있다. 지운 게 아니라 값을 68 → 55로 바꾸고 근거(오너 08-27 재지시·배송 id)를 주석으로 남겼다.
  • UiDaySummary 폐기는 하지 않았다. manifest 후속 ⑨는 "폐기 판단"이고, 이번 배송은 일지 오버레이만 재설계했다. 홈 진입 풀페이지를 같은 턴에 지우면 검증 범위가 배송 밖으로 나간다.

작업 중 드러난 것

  • manifest의 rebase 신고는 "그 파일은 봤다"는 뜻이지 "다른 파일은 깨끗하다"는 뜻이 아니다. 이번 되덮기 2건은 정확히 신고 범위 밖에서 나왔다. 배송 반입은 신고와 무관하게 git diff --name-only <직전 반입 base>..origin/mainchangedFiles를 항상 직접 돌려야 한다.
  • PowerShell 텍스트 왕복이 한글을 깨뜨린다(기존 교훈 재확인). group-props.md 복원은 git checkout + Edit/append로만 처리했고, 셸로 파일 내용을 왕복시키지 않았다.
  • unused 래칫이 재설계의 사각을 잡아준다. 요약 항목이 3개로 줄면서 avgInt·exerciseCount·allSessionCount 계산이 읽는 곳 없이 남았는데 tsc 게이트가 아니라 check-typescript-unused가 잡았다. 배송 zip은 표시만 지우고 계산은 남겨 보내는 경향이 있다.
  • node --test는 디렉터리 인자를 주면 헛통과한다(기존 교훈 재확인) — 인자 없이 실행해 2051건 전수 확인.

5. 적용 결과

Production(https://www.barbelic.com) 배포 번들 실측 — 청크별 마커 계수:

항목전 → 후확인
탭바 높이 토큰--tabbar-h:68px--tabbar-h:55pxmobileRoot-CHZHHzh7.css
세션 표시타임 레일(.dsv-rail) → 세션 카드(.dsv-scards)구 규칙 0회 / 신규 21회 ✅
요약8항(.dsv-ct 소제목 포함) → 3항 스탯박스(.dsv-sumrow)구 규칙 0회 / 신규 2회 ✅
일지 오버레이 내비타이틀 행 → 워드마크 행(.sj-dy-brand)1회 ✅
그룹 표면별 숨단일 규칙 → .gpi-brand·.gb-brand 분리group-CDEHQtpt.css 각 1회 ✅
커스텀 종목 관리내 정보 인라인 카드 → 독립 화면 + 신설 CSSprofile-n6z6voiE.css 359B(.pf-cust 4) · ProfileScreen-BLLI8OpT.js("커스텀 종목 관리"·mobileCustomExerciseManager 각 1) ✅
드로어 진입 마커없음 → profile.customExercises.open셸 청크 2곳 ✅
상류 #872 수리 보존되덮기 위험 → .fc-mbtn{color:var(--ink)}Production CSS에 존재 ✅
상류 #876 스켈레톤 보존되덮기 위험 → gb-skelgroup-*.css 4회 ✅
하루 상세 분석 표면도넛 3종 + 탑세트 TOP 3 노출 → 미노출(주/월 드로어 전용)DayDetailBody-CtnaStnt.js(wk||mo)&&hasDone&&… 게이트 실재 ✅
테스트2051 중 15 실패(반입 직후) → 2051/2051 통과, 표면 축소 후 2052/2052로컬 전수 + CI verify ✅
게이트tsc 0 · unused 래칫 0 신규 · dead-css·brand·utf8·policies·dual-key·ts-scope·boundary·tsconfig·test-manifest·error-cases전부 통과 ✅

미검증: 실기기 시각 확인(세션 카드 헤어라인·체크 위치, 3항 스탯박스 정렬, 탭바 55 체감, 그룹 스와이프 뒤로가기 제스처) — 오너 실기기 확인 대기. 스와이프는 터치 이벤트라 하니스·CI로는 판정할 수 없다.

6. 이번 개선으로 향상된 것

하루 기록이 "읽는 화면"이 됐다 — 분석은 범위 드로어로

세트 표기가 피드·화이트보드와 같은 축약 문법으로 통일됐고, 요약 8항 → 3항에 이어 도넛·탑세트까지 범위 드로어로 넘기면서 하루 화면에는 오늘 뭘 했는지(3항 요약 + 세션 카드)만 남았다. 분포·순위 같은 분석은 주/월 드로어가 맡는다 — 한 화면이 두 목적을 겸하지 않는다.

세트 표기가 세 화면에서 같아졌고, 상태가 내용을 감추지 않는다

같은 운동을 일지·피드·화이트보드에서 볼 때 서로 다른 표기를 번역할 필요가 없어졌다(formatSetRuns 공용). 완료 아닌 세션(예정·미완·동기화 대기)도 같은 카드 문법으로 내용이 보인다 — 전에는 상태에 따라 세트가 감춰졌다.

커스텀 종목 관리가 제 위치로 갔다

내 정보 화면 안의 인라인 카드에서 메뉴 드로어 직결 독립 화면으로 분리됐다. 목록이 길어져도 내 정보 화면을 밀어내지 않고, 진입이 1탭이다.

구조적으로 남는 것

  • 배송 반입의 교집합 검사 절차: manifest 신고와 무관하게 changedFiles ∩ (직전 반입 base..origin/main)을 수신 측이 직접 돌린다. 이번에 이 절차가 없었으면 오너가 아침에 보고한 iOS 파랑이 오후에 재발했다.
  • 마커 장부의 양방향 잠금이 재설계에서도 동작함을 확인: 표시가 사라진 훅(daySummaryExercises)과 새로 등장한 상태값(sync_pending) 양쪽을 designContract.test.mjs가 같은 턴에 잡아냈다.
  • 탭바 높이 계약이 토큰 한 곳에서 개정 가능함을 실증: --tabbar-h 하나를 바꾸고 게이트 기대치 1줄만 따라가면 소비처 12곳이 자동으로 따라온다(이슈 #855 Phase 3의 소유권 역전이 처음으로 값 변경에 쓰였다).
  • 표면이 사라져도 계약은 안 사라진다는 처리 규칙: 표시를 지울 때 테스트를 지우는 대신 그 계약이 아직 살아 있는 표면(다른 모드·다른 플랫폼)으로 앵커를 옮기고, 사라진 사실 자체를 새 단언으로 잠근다. 이번 두 PR에서 앵커 이전 19건·삭제 0건.

남은 것

  • 오너 실기기 확인 — 위 5절 미검증 4항목.
  • manifest 후속 ⑧: 좌→우 스와이프 뒤로가기 계약을 컨테이너 소유 오버레이(홈 → 리포트, 친구 스코프)에도 적용. 전환 규칙 표 = docs/contracts/group-props.md.
  • manifest 후속 ⑨: UiDaySummary(홈 진입 하루 종합 풀페이지)·daySummaryBack 폐기 판단 — 하루 상세가 일지 오버레이로 단일화되면서 중복 표면이 됐다. 폐기하면 마커 daySummaryBack·daySummaryView도 장부에서 함께 내려간다.
  • 게이트 만료: WEEK_BAR_UI(주차 바 비노출, 08-27 지시) 검토 ≈09-24.