Skip to content

종목 상세 누적 숫자 겹침에서 숫자 맞춤·세로 스크롤 계약·폰 목업 정리까지 — 글자 수 추정 폐지, 덮는 페이지 세로 전용, 목업 배경 한 겹·상태바 여백 (2026-09-08)

Phase 현황

Phase내용상태
Phase 0이슈 #1381 분석·계획, 워크트리
Phase 1누적 숫자 자동 축소 — 측정 hook fitInline + 격자 수정 + 공용 RcHeroNum, 글자 수 추정 제거✅ PR #1382 (7d132724)
Phase 2덮는 페이지 세로 스크롤 전용 + 세로 스크롤 컨테이너 계약 테스트✅ PR #1382 (782b3d1c)
Phase 3브라우저 폰 목업 배경 한 겹 + 상태바 47/홈 34 여백✅ PR #1382 (9e2acde8)
Phase 4ci:local full → PR → CI 1회 → 머지 → 버그 리포트 2건·작업 기록

1. 배경

v84(2026-09-01, #1090)에서 종목 상세 히어로가 "최고 기록 | 총 누적" 두 숫자 중심으로 재편되면서 숫자 줄이 "태그 | 숫자 | 단위" 3칸 격자가 됐다. 격자는 숫자 칸이 0까지 줄어들 수 있게(min-width: 0) 선언됐고 글자 크기는 27px 고정이었다. 누적 값이 6자리 이하인 종목이 대부분이라 드러나지 않다가, 오너의 백스쿼트 누적 520,012kg에서 처음 보였다. 같은 날 오너가 데스크톱 브라우저 폭을 줄인 폰 목업의 배경·상단 어색함도 함께 보고했다.

2. 문제 제기

숫자 칸이 글자보다 좁아질 수 있었다

.rc-duo .n em { min-width: 0 } — 세 칸 합이 줄 폭을 넘으면 숫자 칸이 글자보다 좁게 잡히고 글자가 단위 위로 그려진다. 실측: "520,012"(27px) 113px, 줄 폭 390px에서 156 · 375에서 149 · 360에서 141(여유 0). 8자리 "1,520,012"(138px)는 360px에서 18px 겹침. 최고 기록 칸의 "6자 넘으면 27px" 분기도 같은 종류의 추정이었다.

덮는 페이지에 세로 전용 선언이 없었다

.app .pg-overlayoverflow-y: auto만 있어 computed overflow-x가 auto — 안쪽 요소 하나만 넘쳐도 페이지 전체가 옆으로 밀린다. 일반 화면 .screen에는 overflow-x: hidden이 있었고 덮는 페이지(종목 상세·세션 상세·피드·그룹·전체 보기)만 빠져 있었다. 피드 글쓰기 본문·약관 본문도 같은 상태였다.

폰 목업이 캔버스용 분할 배경을 쓰고 상태바 여백이 0이었다

마우스 목업 규칙(@media (min-width:520px) and (pointer:fine))이 1913px 데스크톱 캔버스 레터박스용 "좌 흰색/우 새벽" 두 층을 그대로 그려 390px 폰이 이음새 위에 놓인 것처럼 보였다. --safe-top은 브라우저 env() 값 0이라 헤더가 42px 둥근 모서리 안으로 들어갔다.

3. 해결 방안

원칙

오너 결정 없음(전역 지침 §26 — 기술 방식은 권장안으로 진행). 전제: 목업 여백은 iPhone 14 계열 실제 값(47/34px), 데스크톱 캔버스(≥900px) 레터박스는 손대지 않는다. 전역 지침 §22(땜질 대신 구조)에 따라 글자 수 추정 단계 추가안은 기각.

접근

항목채택기각
숫자 겹침실제 폭 측정 축소(fitInline) + 숫자 칸이 글자보다 좁아질 수 없는 격자 + 두 칸 항상 반반글자 수 단계 확장(.sm/.xs — 글꼴·폭 바뀌면 재발) · 단위를 아래 줄로(디자인 변경, 넘침 못 막음)
가로 스크롤덮는 페이지 전부 overflow-x: hidden + 계약 테스트로 5곳 고정종목 상세에만 선언(다른 덮는 페이지 재발)
폰 목업배경 한 겹 + 상태바/홈 여백 고정배경만(상단 어색함 남음)

4. 적용한 내용

Phase 1 — 누적 숫자 자동 축소 (#1382, 7d132724)

  • lib/fitInline.ts 신규: fitFontSize(avail, side, text, base, min) 순수 계산 → fitInlineNow(line)이 줄의 <em>(숫자) 글자 폭과 나머지 자식(태그·단위) 폭을 재서 필요할 때만 inline font-size를 준다 → useFitInline(ref, key)가 그려진 직후·줄 폭 변화(ResizeObserver, 폭이 바뀔 때만)·document.fonts.ready 뒤에 다시 잰다. 하한 16px.
  • RecordsDetail.tsx: 두 칸의 인라인 IIFE를 공용 RcHeroNum(태그·숫자·단위·훅·탭)으로 합치고 sp.num.length > 5 분기 제거.
  • records.css: .rc-duo minmax(0,1fr) minmax(0,1fr)(긴 숫자가 경계선을 밀지 못함) · .n min-width: 0(줄이 칸 폭에 고정되어 측정 기준이 됨) · emmin-width: 0 제거(숫자 칸은 글자보다 좁아질 수 없음).
  • 테스트 heroNumberFit.test.mjs: 계산 3건(들어감·비례 축소·하한/잘못된 입력) + 격자·배선 앵커 1건.

Phase 2 — 세로 스크롤 전용 (#1382, 782b3d1c)

  • .pg-overlay(primitives.css)·.fd-apbody(feed.css)·.lgd-scroll(legal-doc.css)에 overflow-x: hidden.
  • 테스트 verticalScrollContainersContract.test.mjs: .screen·.pg-overlay·.sheet-body·.fd-apbody·.lgd-scroll 규칙 블록에 overflow-x: hidden|clip 요구. 목록을 늘릴 때는 "화면 폭을 채우는 세로 스크롤 컨테이너"인지 확인.

Phase 3 — 폰 목업 (#1382, 9e2acde8)

  • app-host.css 목업 규칙: 호스트 배경 = var(--lg-desktop-dawn-bg) fixed 한 겹, 장치에 --safe-top: 47px·--safe-bottom: 34px. 앱 CSS는 종전대로 env()만 쓴다.
  • backgroundTokens.test.mjs 목업 앵커 갱신(분할 금지·글로우 한 겹·여백 47/34) · viewport-tiers.md pointer-mockup 행·§3.

주요 결정과 그 근거

  • 측정 기반: 기기에서 7자리가 넘친 직접 계기를 데스크톱 WebKit·Chromium(390/375)에서 재현하지 못했다. 계기를 특정해 막는 대신 실제 그려진 폭으로 맞추면 폭·자릿수·글꼴 어느 계기에도 같은 규칙으로 막힌다.
  • ResizeObserver는 폭 변화에만 반응: 글자 크기 변화로 높이만 바뀐 알림에 다시 재면 측정 순환이 생긴다.
  • 덮는 페이지 전부: 종목 상세만 고치면 세션 상세·피드·그룹에서 같은 문제가 다시 난다(§22).

작업 중 드러난 것

  • 숫자 줄(.n)이 width: 100%인데도 부모 칸보다 넓게 늘어나는 중간 상태(격자 항목 자동 최소 폭)가 있어 clientWidth가 164px로 잡혔다 — .n에도 min-width: 0을 주어 칸 폭(141px)에 고정한 뒤에야 측정이 맞았다.
  • Phase 2 npm run check 중 편집 중이던 Phase 3 파일의 옛 배경 앵커 테스트 1건이 실패했다(범위 밖, Phase 3에서 갱신). 로컬 게이트를 돌리는 동안 다음 Phase 파일을 만지면 결과 해석이 섞인다.
  • ci:local 판정은 verify-only였으나 앱 화면·호스트 배경 변경이라 --full로 브라우저 저니까지 돌렸다.

5. 적용 결과

항목결과
360px·8자리 "1,520,012" 넘침단위 칸 밖 23px → 0px (글자 27 → 22.46px, 단위 간격 5px 유지)
두 칸 폭(360px)142/164px(긴 숫자가 경계 밀림) → 154/154px
.pg-overlay computed overflow-xauto → hidden (.screen·.sheet-body·.fd-apbody hidden)
800×900 목업 호스트 배경 층2(흰 반 분할 + 글로우) → 1(글로우)
800×900 목업 --safe-top / --safe-bottom0 / 0 → 47px / 34px
로컬 게이트npm run check 3195 pass · ci:local full 통과(PR 본문 검증 줄)
CI1회 통과(PR #1382)
미검증기기에서 7자리가 넘친 직접 계기(글꼴 대체·기기 글자 설정) 미확정. 첫 그리기 직후 한 프레임의 시각 품질·목업 인상은 사람 눈으로만 판단 가능

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

큰 숫자가 어떤 폭·자릿수·글꼴에서도 단위와 겹치지 않는다

유저가 어떤 기기로 보든, 누적이 몇 자리든, 웹폰트가 늦게 오든 숫자는 칸에 맞춰 줄어든다. 글자 수 추정이 사라져 다음 폰·다음 글꼴에서 같은 자리를 다시 고칠 일이 없다.

덮는 페이지가 옆으로 밀리지 않는다

종목 상세뿐 아니라 세션 상세·피드·그룹·전체 보기·피드 글쓰기·약관 본문이 세로로만 스크롤된다. 계약 테스트가 선언을 지키므로 새 덮는 페이지가 같은 결함을 갖고 들어오면 PR이 실패한다.

브라우저 폰 목업이 실제 폰처럼 보인다

배경이 한 겹이고 상태바·홈 여백이 실제 값이라 오너가 브라우저에서 보는 모습이 앱과 가깝다.

구조적으로 남는 것

  • lib/fitInline — 히어로 큰 숫자 맞춤 정본(다른 큰 숫자 칸에 재사용).
  • verticalScrollContainersContract — 세로 스크롤 컨테이너 세로 전용 계약.
  • viewport-tiers.md pointer-mockup 규칙(배경 한 겹·여백 47/34) + backgroundTokens 앵커.

남은 것

  • Production 반영 = 다음 릴리스(v0.17.2). 릴리스 머지 뒤 이슈 #1381 [v0.17.2 반영완료]로 닫는다.
  • 데스크톱 캔버스(≥900px)의 "좌백/우새벽" 분할 레터박스는 이번 보고 범위 밖 — 그대로.