피드로 돌아가기
PDF Font Hell - Why Swapping Fonts in PDF Breaks Everything
Dev.toDev.to
Backend

PDF Font Hell - Why Swapping Fonts in PDF Breaks Everything

PDF 폰트 교체 시 인코딩·메트릭·글리프 매핑 구조를 무시하면 레이아웃 붕괴, 문자 깨짐, 커닝 오류 발생

Michael Lahr2026년 3월 24일12advanced

Context

PDF에서 유사한 두 산세리프 폰트(Source Sans → Open Sans)로 교체하면 글리프 바이트 치환만으로는 라인 오버플로우, 단락 리플로우, 문자 깨짐(tofu), 글리프 누락, 자간 오류, 바운딩박스 오류가 동시에 발생한다. 이는 PDF가 폰트를 스타일 속성이 아닌 문자 저장·위치·인코딩·렌더링의 핵심 구조로 설계했기 때문이다.

Technical Solution

  • PDF 폰트 타입 5가지 구조 이해: Type 1(1984년 PostScript 큐빅 베지어, 256 글리프), TrueType(1991년 이차 B-스플라인, 256 글리프), Type 3(PDF 드로잉 명령어, 표준 메트릭 없음), CID Type 0(1990년대 합성, 65,535 글리프, CJK용), OpenType CFF(2000년대, 65,535 글리프)
  • 소스 폰트와 대상 폰트의 인코딩 체인, 메트릭 테이블(hmtx), 글리프 커버리지, 케어닝 데이터를 완전히 파싱하고 매핑하기
  • 변환 행렬이 적용된 텍스트의 경우 스케일·회전·기울임을 고려하여 새 메트릭 재계산하기
  • 의미론적 편집 모델 구축: 페이지의 모든 글리프·위치·폰트·인코딩을 추출 → 단어·라인·단락 구조 분석 → 의미 모델에서 폰트 변경 적용 → 새 폰트의 메트릭·커닝·너비 테이블로 텍스트 재배치 → 콘텐츠 스트림에 올바른 글리프 코드·너비·위치로 재인코딩
  • 폰트 디스크립터, 너비 배열, ToUnicode 맵, 폰트 서브셋 메타데이터를 올바르게 작성하기

Key Takeaway

PDF 폰트 변경은 바이트 수준 치환이 아닌 인코딩·메트릭·글리프 매핑의 세 개 계층을 모두 번역해야 하는 의미론적 연산이며, 이를 무시하면 레이아웃 보존과 접근성이 동시에 손상된다.


PDF 폰트 자동 교체 도구를 구축할 때는 바이트 검색·치환 방식을 피하고, 소스 폰트의 문자 인코딩 테이블(cmap), 가로 메트릭(hmtx), 커닝 데이터(GPOS)를 먼저 완전히 파싱한 후 대상 폰트의 동일 정보와 교차 검증하여 글리프 너비·위치·좌표를 재계산하고 메타데이터를 갱신해야만 레이아웃 붕괴와 문자 깨짐을 방지할 수 있다.

원문 읽기