웹폰트는 디자인의 완성도를 높이지만, 잘못 사용하면 페이지 로딩 속도와 사용자 경험에 큰 영향을 줍니다. 이 글에서는 폰트 로딩의 원리와 최적화 방법을 단계별로 정리합니다.
FOUT와 FOIT 이해하기
브라우저가 웹폰트를 불러오는 동안 텍스트를 어떻게 처리하느냐에 따라 두 가지 현상이 발생합니다.
| 현상 | 설명 | 문제점 |
|---|---|---|
| FOUT Flash Of Unstyled Text |
기본 폰트로 텍스트를 먼저 보여준 뒤 웹폰트로 교체 | 텍스트가 갑자기 바뀌며 레이아웃 이동 발생 |
| FOIT Flash Of Invisible Text |
웹폰트 로드 전까지 텍스트 숨김 | 텍스트가 늦게 나타나 콘텐츠 인식 지연 |
font-display 속성으로 제어하기
@font-face의 font-display 속성으로 로딩 동작을 제어할 수 있습니다.
@font-face {
font-family: 'MyFont';
src: url('/fonts/MyFont.woff2') format('woff2');
font-display: swap; /* 권장값 */
}
| 값 | 동작 | 추천 상황 |
|---|---|---|
auto | 브라우저 기본값 | — |
block | 폰트 로드까지 텍스트 숨김 (FOIT) | 아이콘 폰트 |
swap | 기본 폰트 먼저 표시 후 교체 (FOUT) | 본문 텍스트 ✅ |
fallback | 100ms 숨김 후 교체, 3초 후 기본 폰트 확정 | 중요한 텍스트 |
optional | 빠르게 로드되면 사용, 아니면 기본 폰트 유지 | 장식 폰트 |
preconnect로 연결 미리 시작하기
Google Fonts 같은 외부 CDN을 사용한다면 <link rel="preconnect">로 DNS 조회와 TCP 연결을 미리 시작할 수 있습니다.
<!-- DNS + TCP + TLS 핸드셰이크를 미리 시작 -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- 그 다음 폰트 CSS 로드 -->
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap" rel="stylesheet">
crossorigin 속성이 없으면 폰트 파일 자체의 연결(fonts.gstatic.com)에서 preconnect가 제대로 동작하지 않습니다. 반드시 추가하세요.
폰트 파일 자체를 preload하기
가장 중요한 폰트 파일을 직접 preload하면 더 빠릅니다.
<link
rel="preload"
href="/fonts/Pretendard-Regular.woff2"
as="font"
type="font/woff2"
crossorigin
>
서브셋(Subset) 폰트 사용하기
한국어 폰트는 수천 개의 글리프를 포함하여 파일 크기가 큽니다. 실제 사용하는 글자만 추출한 서브셋을 사용하면 크기를 90% 이상 줄일 수 있습니다.
# pyftsubset으로 서브셋 생성 (fonttools 필요)
pip install fonttools
pyftsubset NotoSansKR-Regular.ttf \
--unicodes="U+AC00-D7A3,U+0030-0039,U+0041-005A,U+0061-007A" \
--layout-features="*" \
--flavor=woff2 \
--output-file="NotoSansKR-subset.woff2"
Variable Font 활용하기
여러 굵기(weight)의 폰트를 각각 불러오는 대신, Variable Font 하나로 모든 굵기를 사용할 수 있습니다.
@font-face {
font-family: 'Pretendard Variable';
src: url('/fonts/PretendardVariable.woff2') format('woff2-variations');
font-weight: 100 900; /* 전체 weight 범위 지원 */
font-display: swap;
}
/* 이제 어떤 weight도 자유롭게 */
h1 { font-weight: 800; }
p { font-weight: 400; }
small { font-weight: 300; }
✅
font-display: swap 사용✅ 외부 CDN에
preconnect 추가✅ 중요 폰트 파일
preload✅
woff2 형식만 사용 (최신 브라우저 100% 지원)✅ 서브셋 또는 Variable Font 적용
실제 성능 측정 — DevTools 활용
폰트 로딩 최적화 전후 효과는 Chrome DevTools의 Performance 탭과 Network 탭으로 직접 확인할 수 있습니다.
- Network 탭 — 폰트 파일 요청 타이밍, 크기, 우선순위 확인. Initiator 컬럼에서 어디서 폰트를 요청하는지 추적
- Performance 탭 — Layout Shift 이벤트 확인. FOUT로 인한 CLS(Cumulative Layout Shift) 점수 측정
- Lighthouse — "Avoid invisible text during webfont loading" 경고와 "Preconnect to required origins" 제안을 점검
측정 시에는 크롬 시크릿 창을 사용하거나 캐시를 비우고 테스트하세요. 캐시된 상태에서는 폰트 로딩 문제가 보이지 않습니다.
Google Fonts vs 자체 호스팅 비교
| 항목 | Google Fonts CDN | 자체 호스팅 |
|---|---|---|
| 설정 난이도 | 매우 쉬움 (링크 태그 한 줄) | 보통 (파일 다운로드 + 설정) |
| 추가 DNS 조회 | 발생 | 없음 (같은 서버) |
| 업데이트 | 자동 (Google 관리) | 수동 관리 필요 |
| GDPR·개인정보 | 사용자 IP가 Google에 전달 | 문제 없음 |
| 성능 | preconnect 필수 | 최적화에 유리 |
한국 서비스라면 Pretendard Variable(jsDelivr CDN 또는 자체 호스팅)이 실용적인 선택입니다. 유럽 사용자가 있는 서비스라면 GDPR 관점에서 자체 호스팅을 고려하세요.
size-adjust로 폰트 교체 흔들림 최소화
FOUT에서 기본 폰트와 웹폰트의 크기 차이로 레이아웃이 흔들리는 문제는 size-adjust 속성으로 완화할 수 있습니다.
/* 시스템 폰트의 크기를 웹폰트에 맞게 조정 */
@font-face {
font-family: 'FallbackFont';
src: local('Apple SD Gothic Neo'), local('Malgun Gothic');
size-adjust: 105%;
ascent-override: 90%;
descent-override: 10%;
}
body {
font-family: 'Pretendard Variable', 'FallbackFont', sans-serif;
}
이 기법은 폰트 교체 시 CLS 점수를 0.01 이하로 낮추는 데 효과적입니다. Chrome 92+, Firefox 92+에서 지원됩니다.
웹폰트 로딩이 Core Web Vitals에 미치는 영향
폰트 최적화는 SEO 핵심 지표인 Core Web Vitals와 직결됩니다.
- LCP (Largest Contentful Paint) — 텍스트가 LCP 요소라면 폰트 로딩 지연이 LCP를 직접 악화시킵니다. 목표: 2.5초 이내
- CLS (Cumulative Layout Shift) — FOUT로 인한 레이아웃 이동. 목표: 0.1 이하.
font-display: swap은 CLS를 유발하지만size-adjust로 완화 가능 - FCP (First Contentful Paint) — FOIT는 FCP를 늦춥니다.
font-display: swap으로 개선
실제 사용자 데이터(Field Data)는 Google Search Console의 Core Web Vitals 리포트에서 확인하고, 실험실 데이터(Lab Data)는 Lighthouse로 측정하는 습관을 들이세요. 두 데이터의 차이가 크다면 지역별, 기기별 편차가 있다는 신호입니다.
폰트 선택이 웹사이트 성격을 결정한다
웹폰트 최적화는 기술적인 문제이기도 하지만, 동시에 디자인과 브랜드 아이덴티티의 문제이기도 합니다. 한글 웹폰트는 영문 폰트와 달리 글자 수가 수천 자에 달해 파일 크기가 기본적으로 크기 때문에, 어떤 폰트를 선택하느냐가 성능에 직접적인 영향을 미칩니다. 나눔고딕, 본고딕(Noto Sans KR), 스포카 한 산스, 프리텐다드 같은 오픈소스 한글 폰트들은 서브셋과 가변 폰트 형식을 모두 지원해서 최적화하기 좋습니다. 반면 아름다운 세리프 폰트나 손글씨체 폰트는 서브셋 지원이 제한적인 경우가 많아서, 특정 섹션에만 부분적으로 적용하는 방식이 현실적입니다.
가변 폰트(Variable Font)는 한 파일 안에 여러 굵기와 너비를 담고 있어서, 여러 weight를 사용하는 사이트라면 파일 수와 전체 용량을 크게 줄일 수 있습니다. 예를 들어 400, 500, 700 세 가지 굵기를 따로 로드하면 세 개의 폰트 파일이 필요하지만, 가변 폰트 하나면 모든 굵기를 커버할 수 있습니다. 가변 폰트는 CSS의 font-variation-settings나 font-weight에 범위를 지정해 사용합니다. 2025년 기준으로 Chromium, Firefox, Safari 모두 가변 폰트를 완전히 지원하므로, 신규 프로젝트에서는 가변 폰트를 기본 선택지로 고려하는 것이 좋습니다.