← 목록
기타 2026-06-14 5KB 읽기 5분

북스 책장넘기기(flip) 재구축 + 모바일/태블릿/PC 최적화

개요

book.crowny.org 리더의 책장넘기기(flip) 모드가 컬럼 피치와 스크롤량 불일치로 페이지 경계서 글자가 잘리던 문제를 결정론적 transform 페이지 모델로 재구축하고, 모바일/태블릿/PC 각각 최적화. 울트라 병렬(독립 2구현 → 적대 판정)로 구현, Chrome 헤드리스로 디바이스 매트릭스 실측 검증.

무엇을 했는지

1. 결정론적 페이지 모델 (정렬 보장)

  • 컬럼/페이지: 모바일(<768px) 1열 / 태블릿·PC(≥768px) 2열 스프레드. PC(≥1024)는 스테이지폭 1100px 캡 센터링.
  • innerW=가용내부폭, gap=거터, cw=(innerW−(cols−1)·gap)/cols, pageWidth=innerW+gap (1·2열 공통).
  • .art.flip-track로 감싸 transform: translateX(−page·pageWidth) (네이티브 스크롤 드리프트 제거, 픽셀정확).
  • .art 폭을 innerW로 핀 + column-count만(column-width 제거) + .art.scrollWidth 단일 측정으로 totalPages 산출.
  • 헤더(crumbs/kch/h1)는 .flip-header absolute 분리(column-span 대체), 스크롤 모드는 display:contents로 래퍼 투명화(무회귀).

2. 디바이스 최적화

  • 모바일: 1쪽, 좌/우 1/3 탭존 + 스와이프(40px 임계), 100dvh−컨트롤 페이지높이, safe-area 인셋.
  • 태블릿: 2쪽 스프레드, 스와이프+버튼.
  • PC: 2쪽 스프레드, 스테이지 1100px 캡 센터링, hover 사이드버튼, 키보드(←→/Space/PageUp·Down).
  • 공통: 페이지표시기 "n/total", resize/회전/글자크기(A±) 시 비율보존 relayout, 다크모드·--fz 유지.

3. 울트라 병렬 (독립 2구현 → 적대 판정)

  • Sonnet 2명이 독립 구현 → Opus 판정자가 실제 Chrome 헤드리스로 양쪽 실측 → A(래퍼 scrollWidth 클리핑 90% 소실)·B(width-override 2-pass 5배 폭발) 양쪽 치명버그 발견 → 교정 합성(구조=A 정적, 측정/이동=B transform − width-override + innerW핀 + scrollWidth 단일측정).

검증 (Chrome 헤드리스 디바이스 매트릭스 — 실측)

  • ?fliptest=1 자가검증: 페이지경계=컬럼경계 정렬 + total·pw≥scrollWidth + 가로오버플로 없음을 DOM에 PASS/FAIL 출력.
  • 12/12 PASS: {crownyai/expert/1, book3/kid/2, ilovecrowny/om/3, crownyai/general/5} × {모바일390, 태블릿820, PC1440}.
  • 페이지수 예: crownyai/expert/1 → 모바일 36p(1열), PC 14p(2열 스프레드). 둘 다 오버스크롤 0.
  • 스크롤모드 무회귀, 게이트웨이 443 + ?shared=1 200.

동반 버그 2건 수정 (검증 중 발견)

  1. 빌드 인라인 JS escape: 소셜 세션 fbHtml이 build-reader.js의 JS 백틱템플릿 안에서 \'(단일)을 써서 출력 시 '로 깨짐 → 챕터 인라인 스크립트 전체 SyntaxError → 소셜 좋아요/추천/게이트 UI가 브라우저서 작동 안 했음(API는 curl로 통과해 잠복). \\'로 수정. flip의 \n\\n도 동일.
  2. 정적 쿼리스트링 404: 정적경로()가 쿼리 미제거 → ?shared=1·?ref=·?fliptest=1 정적파일 404(공유링크 깨짐). 쿼리제거() 선적용으로 수정.

관련 파일

  • 리더 빌더: 웹/build-reader.js — flip CSS(.flip-header/.flip-stage/.flip-track + display:contents 무회귀), flip JS IIFE(relayout/goPage/flipPage/setMode/스와이프·탭존·키보드/페이지표시기/?fliptest 자가검증), fbHtml escape 수정.
  • 서버: 책서버.한선 — 정적경로() 쿼리제거.
  • 배포: bookagent.toau(워치독 respawn), 3책 재빌드.
  • 검증 하니스: /tmp/flip검증.sh (Chrome 헤드리스 --dump-dom, 3뷰포트).
  • 백업: build-reader.js.bak.flip_20260614, 책서버.한선.bak.social_20260613.

함정/교훈 (영속화)

  • build-reader.js 인라인 JS는 백틱템플릿 → \\'·\\n 필수. 검증=출력HTML 인라인스크립트 추출 후 node -c(빌드 스크립트 node -c로는 못 잡음) + 헤드리스 dump로 body class·결과div 확인. (메모리 feedback_buildreader_inline_js_escape)
  • 정적 서버 정적경로()는 쿼리제거 선적용.
  • 시각 검증 불가 메커닉은 독립 2구현+적대판정(헤드리스 실측)으로 신뢰 확보 — 판정자가 코드만으론 안 보이는 측정버그를 실측으로 적발.

잔여 이슈

  • 스와이프/탭존/키보드는 헤드리스 레이아웃 검증엔 안 잡힘 → 실기기 수동 확인 권장(드롭캡 단독잔류·iOS 주소창 dvh 미세변동은 기능무해).
  • 크라우니브라우저(WebKit) display:contents 교차확인 권장.