한글 vs 영문 폰트의 근본적 차이
| 영문 폰트 | 한글 폰트 | |
|---|---|---|
| 글리프(글자) 수 | ~300개 | 11,172개 (완성형 한글) + 한자 + 기호 |
| 폰트 파일 크기 | 15~30KB | 2~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 비동기 로딩 기법입니다.