웹폰트는 디자인의 완성도를 높이지만, 잘못 사용하면 페이지 로딩 속도와 사용자 경험에 큰 영향을 줍니다. 이 글에서는 폰트 로딩의 원리와 최적화 방법을 단계별로 정리합니다.

FOUT와 FOIT 이해하기

브라우저가 웹폰트를 불러오는 동안 텍스트를 어떻게 처리하느냐에 따라 두 가지 현상이 발생합니다.

현상설명문제점
FOUT
Flash Of Unstyled Text
기본 폰트로 텍스트를 먼저 보여준 뒤 웹폰트로 교체 텍스트가 갑자기 바뀌며 레이아웃 이동 발생
FOIT
Flash Of Invisible Text
웹폰트 로드 전까지 텍스트 숨김 텍스트가 늦게 나타나 콘텐츠 인식 지연

font-display 속성으로 제어하기

@font-facefont-display 속성으로 로딩 동작을 제어할 수 있습니다.

@font-face {
  font-family: 'MyFont';
  src: url('/fonts/MyFont.woff2') format('woff2');
  font-display: swap; /* 권장값 */
}
동작추천 상황
auto브라우저 기본값
block폰트 로드까지 텍스트 숨김 (FOIT)아이콘 폰트
swap기본 폰트 먼저 표시 후 교체 (FOUT)본문 텍스트 ✅
fallback100ms 숨김 후 교체, 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-settingsfont-weight에 범위를 지정해 사용합니다. 2025년 기준으로 Chromium, Firefox, Safari 모두 가변 폰트를 완전히 지원하므로, 신규 프로젝트에서는 가변 폰트를 기본 선택지로 고려하는 것이 좋습니다.