NextJS: 폰트 최적화

hwisaac·2023년 3월 12일
3

Next.js

목록 보기
13/29

next/font는 사용자 정의 폰트를 포함하여 모든 폰트 파일을 자동으로 최적화하고 개인 정보 보호와 성능 향상을 위해 외부 네트워크 요청을 제거합니다.

🎥 영상 보기: next/font 사용 방법 알아보기 → YouTube (6분).

개요

next/font에는 모든 폰트 파일에 대한 내장 자체 호스팅이 포함되어 있습니다. 이는 기본적으로 CSSsize-adjust 속성을 사용하여 웹 폰트를 최적으로 로드할 수 있도록 해주므로 레이아웃 시프트가 없습니다.

이 새로운 폰트 시스템은 성능과 개인 정보 보호를 고려하여 모든 Google 폰트를 편리하게 사용할 수 있도록 합니다. CSS 및 폰트 파일은 빌드 시간에 다운로드되어 정적 자산과 함께 자체 호스팅됩니다. 브라우저에서 Google로 요청이 전송되지 않습니다.

Google 폰트

어떤 Google 폰트든 자동으로 자체 호스팅할 수 있습니다. 폰트는 배포에 포함되어 배포와 동일한 도메인에서 제공됩니다. 브라우저에서 Google로 요청이 전송되지 않습니다.

사용할 폰트를 next/font/google에서 함수로 가져와서 시작하세요. 최상의 성능과 유연성을 위해 변수 글꼴을 사용하는 것이 좋습니다.

모든 페이지에서 폰트를 사용하려면 _app.js 파일의 /pages에 추가하면 됩니다. 아래와 같이 작성하세요.

// pages/_app.js
import { Inter } from 'next/font/google';

// 변수 글꼴을 로드하는 경우 글꼴 무게를 지정할 필요가 없습니다.
const inter = Inter({ subsets: ['latin'] });

export default function MyApp({ Component, pageProps }) {
  return (
    <main className={inter.className}>
      <Component {...pageProps} />
    </main>
  );
}

만약 변수 글꼴을 사용할 수 없는 경우, 글꼴 무게(weight)를 지정해야 합니다.

// pages/_app.js
import { Roboto } from 'next/font/google';

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

export default function MyApp({ Component, pageProps }) {
  return (
    <main className={roboto.className}>
      <Component {...pageProps} />
    </main>
  );
}

배열을 사용하여 여러 무게와 스타일을 지정할 수 있습니다.

const roboto = Roboto({
  weight: ['400', '700'],
  style: ['normal', 'italic'],
  subsets: ['latin'],
});

참고: 폰트 이름에 공백이 있는 경우 _를 사용할 수 있습니다. 예를 들어 Titillium WebTitillium_Web으로 표기됩니다.

<head>에 폰트 적용

<head> 내에서 폰트를 적용하려면 다음과 같이 Google Fonts에서 가져온 폰트를 import 한 후 <style> 태그 안에 폰트를 삽입합니다:

// pages/_app.js
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function MyApp({ Component, pageProps }) {
  return (
    <>
      <style jsx global>{`
        html {
          font-family: ${inter.style.fontFamily};
        }
      `}</style>
      <Component {...pageProps} />
    </>
  );
}

단일 페이지에서 폰트 사용

페이지별로 폰트를 적용하려면 다음과 같이 해당 페이지에 직접 폰트를 적용합니다:

// pages/index.js
import { Inter } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });

export default function Home() {
  return (
    <div className={inter.className}>
      <p>Hello World</p>
    </div>
  );
}

하위 집합(subset) 지정하기

Google Fonts는 자동으로 하위 집합(subset)을 만들어 폰트 파일 크기를 줄이고 성능을 개선합니다. 하지만 미리 로드(preload) 할 하위 집합을 명시적으로 지정해야 합니다. preloadtrue인 상태에서 하위 집합을 지정하지 않으면 경고 메시지가 표시됩니다.

하위 집합을 지정하는 방법은 두 가지가 있습니다:

  • 폰트별로 함수 호출 시 하위 집합을 추가합니다.
// pages/_app.js
const inter = Inter({ subsets: ['latin'] });
  • next.config.js에서 모든 폰트에 대해 전역으로 지정합니다.
// next.config.js
module.exports = {
  experimental: {
    fontLoaders: [
      { loader: 'next/font/google', options: { subsets: ['latin'] } },
    ],
  },
};

두 방법 모두 설정된 경우 함수 호출에서 지정한 하위 집합이 사용됩니다.
자세한 내용은 Font API Reference를 참조하세요.

로컬 폰트(Local Fonts)

next/font/localimport하고 로컬 폰트 파일의 src를 지정합니다. 가장 좋은 성능과 유연성을 위해 변수 폰트를 사용하는 것을 권장합니다.

// pages/_app.js
import localFont from 'next/font/local';

// Font files can be colocated inside of `pages`
const myFont = localFont({ src: './my-font.woff2' });

export default function MyApp({ Component, pageProps }) {
  return (
    <main className={myFont.className}>
      <Component {...pageProps} />
    </main>
  );
}

하나의 폰트 패밀리에 여러 파일을 사용하려면 src를 배열로 지정할 수 있습니다:

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',
    },
  ],
});

자세한 내용은 Font API Reference를 참조하세요.

Tailwind CSS와 함께 사용하기

next/font는 CSS 변수를 통해 Tailwind CSS와 함께 사용할 수 있습니다.

아래 예시에서는 next/font/googleInter 폰트를 사용합니다. (Google FontsLocal Fonts에서 다른 폰트를 사용할 수 있습니다.) inter를 변수 옵션과 함께 로드하여 CSS 변수 이름을 정의하고 inter.variable을 사용하여 HTML 문서에 CSS 변수를 추가합니다.

// pages/_app.js
import { Inter } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
});

export default function MyApp({ Component, pageProps }) {
  return (
    <main className={`${inter.variable} font-sans`}>
      <Component {...pageProps} />
    </main>
  );
}

마지막으로 Tailwind CSS 구성 파일에 CSS 변수를 추가합니다:

// tailwind.config.js
const { fontFamily } = require('tailwindcss/defaultTheme');

/** @type {import('tailwindcss').Config} \*/
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-inter)', ...fontFamily.sans],
      },
    },
  },
  plugins: [],
};

이제 font-sans 유틸리티 클래스를 사용하여 요소에 폰트를 적용할 수 있습니다.

프리로딩(Preloading)

사이트의 페이지에서 폰트 함수를 호출하면 해당 폰트가 전역적으로 사용 가능하고 모든 경로에서 프리로드(preload)됩니다. 대신, 해당 파일에서 사용되는 경로(route)에 따라 관련 경로에만 폰트가 프리로드됩니다:

  • 고유 페이지(unique page)인 경우 해당 페이지의 고유 경로(unique route)에 프리로드됩니다.
  • 사용자 정의 앱(custom app)에 있는 경우 /pages 아래의 사이트의 모든 경로에 프리로드됩니다.

폰트 재사용

localFont 또는 Google 폰트 함수를 호출할 때마다 해당 폰트는 응용 프로그램에서 하나의 인스턴스로 호스팅됩니다. 따라서 동일한 폰트 함수를 여러 파일에서 로드하면 동일한 폰트의 여러 인스턴스가 호스팅됩니다. 이러한 경우 다음을 권장합니다.

  • 하나의 공유 파일에서 폰트 로더 함수를 호출합니다.
  • 상수로 내보냅니다.
  • 이 폰트를 사용하려는 각 파일에서 상수를 import합니다.

0개의 댓글