대니
danny's blog@dannywon_dev
발행 35 · 대기 83

1인 개발자. 클로드 코드를 팀처럼 굴린다. 매일 겪은 것만 쓴다.

버그와 함정

CSS overflow: hidden 으로 16:9 PDF 를 뽑다가 두 줄을 날릴 뻔했다

break-before: page 를 잘못 읽어 네 번 헛돌았고, 고친 뒤 재보니 63px 이 넘쳐 있었다

슬라이드 18장짜리 문서를 PDF 로 뽑았는데 페이지가 17장으로 나오는 상황을 겪어본 사람이면 다음 장면도 익숙할 것이다. 짧은 섹션은 아래가 통째로 비고, 긴 섹션은 두 장으로 쪼개져 둘째 장에 몇 줄만 남는다.

2026-08-06, 방과후 제안서를 16:9 PDF 로 뽑아야 했다. 규격은 처음부터 맞았다 — @page { size: 13.333in 7.5in }, 960×540pt, 비율 1.778. 정확히 16:9다. 그런데 섹션 10개짜리 문서가 17장으로 나왔다.

여백을 줄이는 길로 네 번 돌았다

처음엔 여백 문제로 봤다. 그래서 이렇게 돌았다.

  1. 32장 — 화면 그림이 인쇄에서 1단으로 풀렸다. 인쇄에서는 화면 폭 조건(min-width)이 화면처럼 안 걸린다. 가로 2단을 못 박아 32→21장
  2. 5쪽이 통째로 백지 — 「제목은 뒤 내용과 떨어지지 마라(break-after: avoid)」를 걸어놨는데, 뒤따르는 그림이 한 장보다 커서 제목까지 통째로 밀렸다. 그 바람에 앞 장이 비었다. 규칙을 빼서 21→20장
  3. 제목만 있는 장 — 그림이 조금 커서 제목 아래 첫 줄이 안 들어갔다. 그림 폭을 줄여 20→17장
  4. 그 사이에 padding-bottom: 2.4rem → 0 도 해봤는데 출력 PDF 가 바이트 단위로 똑같았다. 내 수정이 효과가 없었다는 뜻인데, 그때는 캐시를 의심했다

두더지잡기였다. 하나를 잡으면 다른 데가 튀어나왔다.

break-before: page 를 잘못 읽고 있었다

다른 세션이 같은 규격으로 뽑은 문서와 나란히 놓고 뜯어보니 원인이 나왔다.

break-before: page 는 **「여기서 새 장을 시작해라」**만 말한다. 「한 장을 넘지 마라」는 말이 아니다.

그래서 섹션 높이가 그대로 흘러갔다. 720px 보다 짧으면 아래가 비고, 길면 다음 장으로 넘쳤다. 여백을 아무리 줄여도 못 고치는 게 당연했다 — 나는 넘치는 양을 줄이고 있었지 넘치는 것 자체를 막고 있지 않았다.

높이를 못 박았다.

.slide {
  width: 1280px;
  height: 720px;      /* min-height 가 아니다. min- 이면 또 늘어난다 */
  overflow: hidden;
}

결과는 18장 = 18슬라이드. 페이지 수가 슬라이드 수와 같아졌고, 백지도 제목만 있는 장도 없어졌다.

여기가 진짜 함정이었다

overflow: hidden 은 넘친 걸 안 보이게 할 뿐 알려주지 않는다.

고쳤다고 생각하고 넘어갈 뻔했는데, 넘겨받은 처방에 "만든 뒤에 반드시 재라" 가 적혀 있어서 측정 스크립트를 돌렸다. 슬라이드마다 자식 요소 아래 끝을 재서 720 - 아래여백 - 끝 을 구하는 것이다.

14장 -63px  🔴 넘침

한 장이 63px 넘쳐 있었다. 화면으로는 멀쩡해 보였고, PDF 페이지 수도 18장으로 정확했다. 그 상태로 나갔으면 문장 두 줄이 조용히 사라진 문서를 대표님께 보냈을 것이다.

맺음 문장을 앞 장으로 옮기고 그림 높이를 320→288px 로 줄여 해결했다. 다시 재니 제일 빠듯한 장이 34px 남았다.

남긴 규칙

~/.claude/rules/print-pdf.md 를 새로 만들었다. 핵심 세 줄이다.

  • height 를 못 박는다 (min-height 아님) + overflow: hidden
  • 만든 뒤 잰다 — 안 재면 잘린 채 나간다
  • 검산은 페이지 수 = 슬라이드 수. 더 많으면 어딘가 넘친 것이다

같은 날 하나 더 있었다. 헤드리스 브라우저로 폰 화면(430px)을 찍었더니 오른쪽이 잘려 보였다. 격자 문제인 줄 알고 열 수를 고쳤는데도 여전했다. 두 번째 추측에 들어가려다 실제로 재보니 scrollWidth=430, 넘치는 요소 0개 — 화면은 처음부터 멀쩡했고 스크린샷만 잘려 있었다. 없는 버그를 고치고 있었던 것이다.

두 번 다 눈으로 본 것과 실제로 잰 것이 달랐다.

← 목록으로