pile·
프론트엔드·vercel-blogVercel Blog·

Next.js next/font로 웹 폰트 CLS 없이 최적화하기

웹 폰트 로딩은 FOUC(Flash of Unstyled Content)와 CLS(Cumulative Layout Shift)를 유발해 Core Web Vitals 점수와 SEO를 떨어뜨린다. Next.js 13의 next/font는 기존에 수동으로 해야 했던 6가지 최적화를 자동화하고, size-adjust로 폴백 폰트를 완벽히 매칭해 CLS를 원천 차단한다.

핵심 포인트
  • 폰트 로딩의 두 가지 문제: FOUC(폰트 로드 전 시스템 폰트 노출)와 CLS(폰트 교체 시 레이아웃 이동).
  • 기존 해결책 6가지: 자체 호스팅, preload 메타 태그, 라틴 서브셋, 폴백 폰트 지정, font-display: optional, 방문 이력 기반 클라이언트 JS — 모두 수동이다.
  • next/font는 이 6가지를 자동화: Google Fonts를 빌드 시 자체 호스팅하고 외부 요청을 제거한다.
  • size-adjust CSS 속성을 서버에서 자동 계산해 폴백 폰트 크기를 조정 → 폰트 교체 전후 레이아웃이 완벽히 일치.
  • App Router에서 특정 레이아웃에만 임포트해 필요한 페이지에만 프리로드 범위를 좁힐 수 있다.
상세 정리
  • 문제 정의: 외부 폰트를 로드할 때 네트워크 요청이 완료될 때까지 시스템 폰트가 보이다가(FOUC) 교체 시 레이아웃이 이동한다(CLS). CLS는 구글 Core Web Vitals 지표로 SEO에 직접 영향을 준다.
  • 기존 전략 1 — 자체 호스팅: Google Fonts URL 대신 폰트 파일을 직접 서빙해 제3자 네트워크 요청을 제거한다.
  • 기존 전략 2 — preload: head의 meta 태그로 브라우저가 폰트를 미리 다운로드하도록 힌트를 준다.
  • 기존 전략 3 — 서브셋 제한: 필요한 문자(라틴)만 프리로드해 다운로드 크기를 줄인다.
  • 기존 전략 4 — 폴백 폰트: 커스텀 폰트와 유사한 시스템 폰트를 font-family 스택에 지정해 FOUC를 줄인다.
  • 기존 전략 5 — font-display: optional: 폰트 로드가 오래 걸리면 폰트를 교체하지 않아 레이아웃 이동을 방지한다. 단 캐시에 없으면 첫 방문에서 시스템 폰트로 렌더된다.
  • 기존 전략 6 — 방문 이력 감지 클라이언트 JS: localStorage로 재방문자를 감지하면 캐시된 폰트를 즉시 사용해 zero-shift를 달성한다. 단 JS 의존성이 생긴다.
  • next/font 자동화: Inter({ display: 'swap', subsets: ['latin'], variable: '--font-sans' }) 한 줄로 자체 호스팅 + 서브셋 + font-display가 자동 적용된다.
  • size-adjust 핵심: 빌드 시 서버에서 대상 폰트와 폴백 폰트의 메트릭 차이를 계산해 size-adjust CSS 값을 자동으로 생성한다. 폰트 교체 전후 글자 크기가 동일해져 레이아웃 이동이 0이 된다.
  • TailwindCSS 호환: CSS 변수(--font-sans)로 폰트를 노출하면 기존 TailwindCSS 설정을 수정 없이 재사용할 수 있다.
  • App Router 세분화: 특정 route segment의 layout.tsx에서만 임포트하면 해당 페이지에서만 폰트가 프리로드되어 불필요한 네트워크 요청을 제거한다.
왜 읽나웹 폰트로 인한 CLS를 제거하고 Core Web Vitals를 개선하려는 프론트엔드 개발자에게, next/font의 동작 원리와 size-adjust 메커니즘을 이해하는 레퍼런스.
vercel-blog
Vercel Blog 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 프론트엔드·LINE EngineeringLINE Engineering·

    AI로 웹 엔지니어 없이 LINE 앱 안에서 그룹 영상 통화 서비스 만들기

    LINE Planet 팀의 PM과 Android 엔지니어 두 명이 웹 전문 엔지니어 없이 LINE 앱 내에서 그룹 영상 통화 서비스를 개발한 과정을 다룬다. LIFF(LINE Front-end Framework)와 LINE Planet SDK를 활용해 React/Vite 기반 웹 앱을 구성했고, Firebase Cloud Functions로 별도 서버 인프라 없이 구현을 완료했다.

    #react#webrtc#firebase+2