개발 공부/Next.js

Next.js의 폰트 최적화: CLS 개선과 사용자 경험 향상하기

Ryomi 2024. 12. 30. 11:03
728x90
반응형

 

들어가며: 웹 폰트 최적화가 필요한 이유

웹 개발에서 폰트는 브랜딩과 사용자 경험에 중요한 역할을 한다. 하지만 최적화되지 않은 웹 폰트는 성능 저하와 사용자 경험 악화를 초래할 수 있다. 특히 웹 바이탈 측정 요소 중 하나인 Cumulative Layout Shift (CLS)와 관련된 문제는 매우 중요하다.

Cumulative Layout Shift (CLS) 이해하기

CLS란?

- CLS는 Google의 Core Web Vitals 중 하나로, 페이지 로딩 중 발생하는 예기치 않은 레이아웃 변화를 측정하는 지표다.

CLS가 중요한 이유

  1. 사용자 경험
    • 갑작스러운 레이아웃 변화는 사용자의 불편을 초래
    • 잘못된 클릭이나 터치를 유발할 수 있음
  2. SEO 영향
    • Google은 CLS를 검색 순위 요소로 고려
    • 낮은 CLS 점수는 더 낮은 검색 순위로 이어질 수 있음

 

폰트 로딩이 CLS에 미치는 영향

일반적인 폰트 로딩 과정

  1. 초기 렌더링: 시스템 폰트 사용
  2. 웹 폰트 다운로드
  3. 폰트 교체
  4. 레이아웃 변화 발생
/* 전통적인 방식의 웹 폰트 적용 */
@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/CustomFont.woff2') format('woff2');
}

body {
  font-family: 'CustomFont', system-ui, sans-serif;
}

발생하는 문제점

  1. FOUT (Flash of Unstyled Text)
    • 시스템 폰트가 웹 폰트로 교체될 때 발생하는 깜빡임
  2. FOIT (Flash of Invisible Text)
    • 폰트 로딩 중 텍스트가 보이지 않는 현상
  3. 레이아웃 변화
    • 폰트 교체 시 텍스트 크기와 간격 변화로 인한 레이아웃 이동

 

Next.js의 폰트 최적화 솔루션

1. next/font 사용하기

  • font를 빌드 타임에 다운로드
    • Next.js는 지정된 커스텀 폰트를 빌드 과정에서 다운로드하고, 이를 정적 자산과 함께 호스팅 한다.
    • 사용자 브라우저는 폰트를 추가로 다운로드할 필요가 없으므로 렌더링 속도가 빨라진다.
  • CLS 방지
    • Next.js는 폰트가 로드되기 전에 정확한 텍스트 크기와 간격 정보를 제공하여 레이아웃 이동을 방지한다.
    • 이를 통해 텍스트가 초기 렌더링 시 시스템 폰트를 사용하더라도 크기가 변하지 않아 시각적 안정성이 유지된다.
import { Inter, Roboto } from 'next/font/google'

// 구글 폰트 설정
const inter = Inter({
  subsets: ['latin'],
  display: 'swap',
})

// 로컬 폰트 설정
const localFont = localFont({
  src: './fonts/CustomFont.woff2',
  display: 'swap',
})

export default function Layout({ children }) {
  return (
    <html lang="en" className={inter.className}>
      <body>{children}</body>
    </html>
  )
}

2. 주요 최적화 기능

// 가변 폰트 설정
const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter', // CSS 변수로 사용 가능
  display: 'swap',
  preload: true,
  fallback: ['system-ui', 'arial'], // 폴백 폰트 지정
  adjustFontFallback: true, // 자동 폰트 메트릭 조정
})

3. CSS에서 활용

/* 글로벌 CSS */
:root {
  --font-inter: 'Inter', system-ui, sans-serif;
}

body {
  font-family: var(--font-inter);
}

 

예시

1. 기본 설정

// app/ui/fonts.ts
import { Inter, Lusitana } from "next/font/google";

export const inter = Inter({ 
  subsets: ["latin"],
  display: "swap",
  preload: true,
});

export const lusitana = Lusitana({
  subsets: ["latin"],
  weight: ["400", "700"],
  display: "swap",
});

2. 레이아웃 적용

// app/layout.js
import "./ui/global.css";
import { inter } from "./ui/fonts";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={`${inter.className} antialiased`}>{children}</body>
    </html>
  );
}

3. 컴포넌트에서의 사용

// app/page.tsx
import { lusitana } from "./ui/fonts";

export default function Header() {
  return (
    <h1 className={`${lusitana.className} text-lg`}>
      Test
    </h1>
  )
}

 

성능 최적화 팁

  1. 폰트 서브셋 활용
const inter = Inter({
  subsets: ['latin'],
  // 필요한 문자셋만 포함하여 파일 크기 감소
})

  1. 가변 폰트 사용
const inter = Inter({
  variable: '--font-inter',
  // 다양한 폰트 웨이트를 하나의 파일로 관리
})

  1. preload 설정
const inter = Inter({
  preload: true,
  // 중요한 폰트는 미리 로드
})

 

성능 측정과 모니터링

  1. Chrome DevTools 활용
    • Performance 탭에서 폰트 로딩 시간 확인
    • Network 탭에서 폰트 다운로드 상태 모니터링
  2. Lighthouse 점수 확인
    • CLS 점수 모니터링
    • 폰트 관련 성능 개선 제안 확인

 

결론

Next.js의 폰트 최적화 기능을 활용하면:

  1. CLS 문제를 효과적으로 해결 가능
  2. 폰트의 로딩 성능 개선
  3. 더 나은 사용자 경험을 제공 가능

특히 next/font의 자동 최적화 기능은 개발자가 별도의 복잡한 설정 없이도 최적의 폰트 성능을 달성할 수 있게 해준다.

728x90
반응형