Font Optimization

김동현·2026년 3월 4일

next.js 공식문서 번역

목록 보기
13/79

next/font 모듈은 폰트를 자동으로 최적화해 주고, 개인정보 보호와 성능 향상을 위해 외부 네트워크 요청을 제거해 줍니다.

👨‍🏫 강사의 부연 설명:
이게 무슨 의미인지 조금 더 덧붙여 볼게요. 보통 구글 폰트 같은 외부 폰트를 쓰면 브라우저가 구글 서버에 접속해서 폰트를 다운로드해야 하잖아요? 이 과정에서 로딩이 지연되고 성능이 떨어질 수 있는데, next/font를 쓰면 우리가 프로젝트를 빌드할 때 폰트를 아예 다운받아서 우리 서버에 같이 둬버려요. 그래서 사용자의 브라우저가 외부로 네트워크 요청을 보낼 필요가 아예 사라지는 거죠! 보안상으로도 훌륭하고 로딩 속도도 훨씬 빨라집니다.

이 모듈에는 어떤 폰트 파일이든 적용 가능한 내장형 셀프 호스팅(built-in self-hosting) 기능이 포함되어 있어요. 즉, 레이아웃 이동(Layout Shift) 현상 없이 웹 폰트를 최적의 상태로 불러올 수 있다는 뜻입니다.

💡 면접 & 실무 팁:
여기서 말하는 '레이아웃 이동(Layout Shift)' 방지는 프론트엔드 면접에서 정말 자주 묻는 CLS(Cumulative Layout Shift) 최적화와 관련이 깊어요. 폰트가 늦게 로딩되면서 기본 폰트에서 웹 폰트로 바뀔 때 화면 텍스트가 덜컥하고 움직이는 현상(FOUT/FOIT)을 막아주기 때문에, UX를 극적으로 개선할 수 있습니다.

next/font를 사용하려면, 먼저 next/font/local이나 next/font/google에서 모듈을 임포트(import) 하세요. 그다음 적절한 옵션을 넣어서 함수처럼 호출하고, 폰트를 적용하고 싶은 요소의 className에 설정해 주면 됩니다. 예를 들면 이렇게요:

import { Geist } from 'next/font/google'

const geist = Geist({
  subsets: ['latin'],
})

export default function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" className={geist.className}>
      <body>{children}</body>
    </html>
  )
}
import { Geist } from 'next/font/google'

const geist = Geist({
  subsets: ['latin'],
})

export default function Layout({ children }) {
  return (
    <html className={geist.className}>
      <body>{children}</body>
    </html>
  )
}

폰트는 해당 폰트가 사용된 컴포넌트 내에서만 적용(스코프)됩니다. 만약 애플리케이션 전체에 폰트를 적용하고 싶다면, 루트 레이아웃(Root Layout) 파일에 추가해 주시면 돼요.


Google fonts (구글 폰트)

여러분이 원하는 어떤 구글 폰트든 자동으로 셀프 호스팅할 수 있어요. 폰트들은 정적 자산(static assets)으로 저장되어서 여러분이 배포한 사이트와 동일한 도메인에서 제공됩니다. 이 말은 즉, 사용자가 사이트에 방문했을 때 브라우저가 구글 서버로 어떠한 요청도 보내지 않는다는 걸 의미해요.

구글 폰트를 사용하려면, next/font/google에서 원하는 폰트를 임포트해서 시작하면 됩니다:

import { Geist } from 'next/font/google'

const geist = Geist({
  subsets: ['latin'],
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={geist.className}>
      <body>{children}</body>
    </html>
  )
}
import { Geist } from 'next/font/google'

const geist = Geist({
  subsets: ['latin'],
})

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

최고의 성능과 유연성을 얻으려면 가변 폰트(variable fonts)를 사용하는 것을 권장해요. 하지만 가변 폰트를 사용할 수 없는 상황이라면, 폰트의 굵기(weight)를 명시해 주어야 합니다:

👨‍🏫 강사의 부연 설명:
가변 폰트(Variable Font)란 하나의 폰트 파일 안에 여러 가지 굵기와 스타일 정보가 모두 들어있는 최신 폰트 포맷이에요. 예전에는 굵기 400짜리 파일 하나, 700짜리 파일 하나를 각각 따로 다운받아야 했다면, 가변 폰트는 파일 하나만으로도 CSS를 통해 자유자재로 굵기를 조절할 수 있어서 성능 면에서 훨씬 유리합니다. 최신 프론트엔드 생태계에서는 아주 중요한 개념이죠!

import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={roboto.className}>
      <body>{children}</body>
    </html>
  )
}
import { Roboto } from 'next/font/google'

const roboto = Roboto({
  weight: '400',
  subsets: ['latin'],
})

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

Local fonts (로컬 폰트)

내 컴퓨터나 프로젝트 폴더에 있는 로컬 폰트를 사용하려면, next/font/local에서 임포트한 뒤 로컬 폰트 파일의 src 경로를 지정해 주면 됩니다. 폰트 파일은 public 폴더에 저장하거나 app 폴더 내부에 함께 배치(co-located)할 수 있어요. 예를 들면 아래와 같습니다:

💡 실무 팁:
피그마(Figma) 등을 사용해서 디자인을 하거나 넘겨받을 때, 구글 폰트에 없는 상업용 폰트나 기업 전용 폰트(woff2 등)를 써야 하는 경우가 실무에서는 정말 많습니다. 그럴 때 바로 이 localFont 방식을 사용하시면 됩니다! public 폴더에 넣어도 되지만, 요즘엔 유지보수를 위해 폰트를 사용하는 컴포넌트 바로 옆(app 폴더 내부)에 같이 두는 co-location 방식도 많이 쓰이니 참고해 보세요.

import localFont from 'next/font/local'

const myFont = localFont({
  src: './my-font.woff2',
})

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en" className={myFont.className}>
      <body>{children}</body>
    </html>
  )
}
import localFont from 'next/font/local'

const myFont = localFont({
  src: './my-font.woff2',
})

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

만약 하나의 폰트 패밀리(family)에 여러 개의 파일을 사용하고 싶다면, src를 배열(array) 형태로 작성할 수 있습니다:

const roboto = localFont({
  src: [
    {
      path: './Roboto-Regular.woff2',
      weight: '400',
      style: 'normal',
    },
    {
      path: './Roboto-Italic.woff2',
      weight: '400',
      style: 'italic',
    },
    {
      path: './Roboto-Bold.woff2',
      weight: '700',
      style: 'normal',
    },
    {
      path: './Roboto-BoldItalic.woff2',
      weight: '700',
      style: 'italic',
    },
  ],
})

API Reference (API 참조)

Next.js 폰트 기능의 전체 기능 세트를 보시려면 API 참조 문서를 확인해 보세요.

  • Font (폰트)
    • 내장된 next/font 로더를 사용하여 웹 폰트 로딩 최적화하기.

모든 문서의 의미론적 개요(semantic overview)를 보려면 https://nextjs.org/docs/sitemap.md 문서를 참고하세요.

이용 가능한 모든 문서의 인덱스(목록)를 보려면 https://nextjs.org/docs/llms.txt 문서를 참고하세요.

profile
프론트에_가까운_풀스택_개발자

0개의 댓글