한글 vs 영문 폰트의 근본적 차이


영문 폰트한글 폰트
글리프(글자) 수~300개11,172개 (완성형 한글) + 한자 + 기호
폰트 파일 크기15~30KB2~5MB
서브셋 가능성쉬움 (사용 글자 예측 가능)어려움 (어떤 글자가 나올지 예측 불가)

영문 폰트는 하나의 작은 woff2 파일을 preload하면 끝이지만, 한글은 어떤 글자가 페이지에 등장할지 빌드 타임에 알 수 없기 때문에 전략이 완전히 다릅니다.

Pretendard Dynamic Subset이 하는 일

Pretendard의 dynamic-subset CSS는 이 문제를 unicode-range 기반 분할로 해결합니다:

전체 한글 11,172자 → 92개의 woff2 파일로 쪼갬 → 각 파일에 unicode-range 지정 → 브라우저가 페이지에 실제 사용된 글자만 해당 파일을 다운로드

예를 들어 페이지에 “가고기다”만 있으면, 92개 중 subset.91 파일 1개만 다운로드됩니다. 이것 자체는 훌륭한 전략입니다.

그런데 왜 PageSpeed가 낮아지는가?

문제는 **92개의 **@font-face를 선언한 CSS 파일 자체의 로딩 방식에 있습니다:

[최적화된 흐름]

1. 브라우저가 HTML을 파싱
2. <link rel="preconnect" href="jsdelivr"> → DNS+TLS를 미리 수립
3. <link rel="preload" ...subset.91.woff2> → 가장 빈번한 한글+라틴 폰트를 즉시 다운로드 시작
4. <style> 인라인 @font-face → subset.91에 대한 선언이 이미 HTML에 있으므로 외부 CSS 없이 바로 적용 가능
5. ✅ 첫 화면 렌더링 시작 (subset.91으로 대부분의 텍스트가 이미 Pretendard로 렌더)
6. <link media="print" onload="this.media='all'"> → 나머지 92개 subset CSS를 백그라운드에서 비동기 로드
7. 사용자가 스크롤하면서 추가 한글 글자를 만나면 그때 해당 subset만 추가 다운로드

핵심: 53KB CSS가 렌더를 막지 않고, 가장 자주 쓰이는 글자(가, 고, 기, 다, 사, 이, 하 등 + 영문 전체)는 preload로 즉시 렌더됩니다.

media="print" onload="this.media='all'"** 패턴**

<link rel="stylesheet" href="..." media="print" onload="this.media='all'" />
  • media="print" → 브라우저는 “이건 인쇄용이니 화면 렌더와 무관”하다고 판단 → 렌더 블로킹 안 함

  • 다운로드가 완료되면 onload가 실행되어 media='all'로 전환 → 모든 미디어에 적용

  • <noscript> 폴백은 JS가 비활성화된 환경에서도 폰트가 로드되도록 보장

이것은 web.dev에서 권장하는 표준 패턴이고, 2026년 현재에도 가장 널리 쓰이는 CSS 비동기 로딩 기법입니다.