[Next.js] Next.js의 next/font에 대해서 (공식문서 및 최적화 테크닉)

Date:

카테고리:

태그:

Font Optimization

next/font

  • 자동으로 글꼴 최적화 (사용자 지정 글꼴 포함)
  • 외부 네트워크 요청을 제거 (개인정보 보호, 성능 개선)

🎥 next/font 에 대한 유튜브 영상 (6분)

  • next/font 특징

    • CSS 및 글꼴 파일은 빌드 시 다운로드되며 나머지 정적 에셋과 함께 자체 호스팅
    • 브라우저에서 Google에 요청을 보내지 않음

      • [Appendix] next/font 의 pre-download
        • 빌드 타임에 글꼴 미리 다운로드 (웹 폰트의 경우) → 로컬 디렉토리에 저장
        • HTML파일이 로컬 파일을 link하는 방식으로 구성 됨
        • 다른 도메인 간 연결을 위한 handshake 과정 생략 → 체감 속도 향상
      • CSS의 size-adjust 속성 이용한 layout shift 방지

하나의 글꼴 사용하기

Google 글꼴 사용 하기

  • 자체 호스팅 기능을 통해 브라우저에서 구글에 별도 요청 🚫
  • next/font/google에서 사용하려는 글꼴을 함수로 가져와서 시작
  • 최상의 성능과 유연성을 위해 가변 글꼴을 사용하는 것이 좋습니다

    종류 특징
    가변 글꼴 여러 스타일의 버전(굵기 등)이 한 파일에 통합되어 있는 openType 글꼴
    정적 글꼴 스타일 별 별도의 파일을 가지는 기존의 글꼴

    [Appendix] 가변 글꼴 vs 정적 글꼴에 대한 상세한 아티클 (TLTR;)
    [참고 링크] Variable fonts (가변 폰트) | WIT블로그
    [Link] Google Fonts 내 가변 글꼴 리스트
    [참고 링크] Variable Fonts - Google Fonts
    [Appendix] 나무위키 내 한글 가변 글꼴 리스트
    [참고 링크] https://namu.wiki/w/가변 글꼴

  • 모든 페이지에서 글꼴 사용 시 pages/_app.js 에 글꼴 추가

    import { Inter } from "next/font/google";
    
    // 가변 글꼴인 inter의 경우 굵기 설정 불필요
    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";
    
    // 정적 글꼴인 Roboto의 경우 굵기 설정이 필요
    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"], // 지원 언어 (라틴 알파벳)
      display: "swap", // 로딩 전략 (페이지가 로드되면서 사용 가능한 경우 즉시 폰트를 바꿉)
    });
    

    [TIP] 폰트 사이에 띄어 쓰기가 있는 경우 언더스코어( 사용. E.g) Roboto_\__Mono

<head>에 글꼴 적용하기

  • head 안에 글꼴을 삽입 → 래퍼와 클래스명 없이 글꼴을 사용!!

    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 글꼴은 자동적으로 subset 방식

    • 글꼴 파일의 크기가 줄어들고 성능 향상
    • 미리 로드할 subset을 정의해야 함 (preload 상태에서 subset 미 지정 시 🚨경고🚨)

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

여러 글꼴 사용하기

두 가지 접근 방법이 존재

  • [방법 1] 글꼴을 내보내고 가져온 다음 필요한 곳에 클래스명을 적용하는 유틸리티 함수 사용

    • 글꼴이 렌더링될 때만 글꼴이 preload

      // app/fonts.ts
      
      import { Inter, Roboto_Mono } from "next/font/google";
      
      export const inter = Inter({
        subsets: ["latin"],
        display: "swap",
      });
      
      export const roboto_mono = Roboto_Mono({
        subsets: ["latin"],
        display: "swap",
      });
      
    • [방법 2] CSS 변수를 생성하여 원하는 CSS 솔루션과 함께 사용

      • Inter가 전역적으로 적용되고 모든 <h1> 태그의 스타일이 Roboto Mono로 지정됩

          // app/global.css
        
          html {
            font-family: var(--font-inter);
          }
        
          h1 {
            font-family: var(--font-roboto-mono);
          }
        
❗ 여러 글꼴 사용 시 다운로드 해야하는 리소스가 늘어나므로 신중히 사용할 것!!

로컬 글꼴 사용 하기

  • next/font/local 을 불러와 로컬 글꼴 파일의 src 지정 (가변 글꼴 추천)

    **import localFont from 'next/font/local'**
    
    // 폰트 파일은 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",
        },
      ],
    });
    

    자세한 내용은 글꼴 API 문서를 참조

테일윈드 CSS 와 함께 사용하기

  • next/fontCSS 변수를 통해 Tailwind 와 함께 사용 가능
  • CSS variable 이름을 정의하고 inter에 할당
  • inter.variable을 사용하여 HTML 문서에 CSS 변수를 추가

    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.config.js에 CSS 변수를 추가

    **// tailwind.config.js**
    
    /** @type {import('tailwindcss').Config} */
    
    module.exports = {
      content: [
        './pages/**/*.{js,ts,jsx,tsx}',
        './components/**/*.{js,ts,jsx,tsx}',
        './app/**/*.{js,ts,jsx,tsx}',
      ],
      theme: {
        extend: {
          fontFamily: {
            **sans: ['var(--font-inter)'],**
            mono: ['var(--font-roboto-mono)'],
          },
        },
      },
      plugins: [],
    }
    
  • font-sansfont-mono 유틸리티 클래스를 사용하여 요소에 글꼴을 적용 가능

기타

사전 로드 (preload)

  • 페이지에서 글꼴 함수 호출 시 페이지의 타입에 따라 관련 경로에서만 preload

    종류 위치 적용
    특정 페이지 /pages 하위 페이지 내 특정 경로에서 preload
    커스텀 앱 /pages/_app /pages 하위 모든 경로에서 preload

글꼴 재사용

  • localFont 또는 Google 글꼴 함수를 호출 시 하나의 인스턴스로 호스팅 됨
  • 여러 파일에서 동일한 글꼴 함수를 로드 시 여러 인스턴스가 호스팅 됨 (중복)
  • 적절한 재사용 방법

    • 하나의 공유 파일에서 글꼴 로더 함수를 호출합니다.
    • 상수로 내보내기
    • 글꼴을 사용하려는 각 파일에서 상수를 가져옵니다.
      [Appendix] 공유 파일 예시 코드

      // styles/fonts.ts
      
      import { Inter, Lora, Source_Sans_Pro } from "next/font/google";
      import localFont from "next/font/local";
      
      // define your variable fonts
      const inter = Inter();
      const lora = Lora();
      
      // define 2 weights of a non-variable font
      const sourceCodePro400 = Source_Sans_Pro({ weight: "400" });
      const sourceCodePro700 = Source_Sans_Pro({ weight: "700" });
      
      // define a custom local font where GreatVibes-Regular.ttf is stored in the styles folder
      const greatVibes = localFont({ src: "./GreatVibes-Regular.ttf" });
      
      export { inter, lora, sourceCodePro400, sourceCodePro700, greatVibes };
      
      **// tsconfig.json**
      
      {
        "compilerOptions": {
          "paths": {
            "@/fonts": ["./styles/fonts"]
          }
        }
      }
      
      // app/about/page.tsx
      
      import { greatVibes, sourceCodePro400 } from "@/fonts";
      

      [reference] https://nextjs.org/docs/app/api-reference/components/font

Next.js 카테고리 내 다른 글 보러가기

첫 번째 글입니다 가장 최근 글입니다

댓글 남기기