Next.js Git Blog (4): 폰트 설정 및 최적화
목차
소개#
보기 좋은 떡이 먹기도 좋다고, 블로그 인상에 폰트가 주는 영향은 상당히 크다고 생각된다.
이번 포스팅에서는 Next.js 환경에서 폰트를 불러오는 두 가지 방식(Google Fonts, Local Fonts)을 살펴보고자 한다.
사용할 폰트 조합:
- 코드 영역: Fira Code
- 본문 영역: Pretendard
설정 준비#
Next.js는 next/font를 통해 폰트를 최적화한다. 따라서 먼저 폰트 설정을 한곳에서 관리할 수 있도록 별도의 파일을 준비하자.
src
└── fonts
└── index.ts📌 왜 public 디렉토리에 직접 넣지 않을까?
물론 public 폴더에 넣고 경로로 불러올 수도 있다. 하지만
next/font기능을 사용하면 빌드 타임에 폰트 파일을 자동으로 최적화하고, 필요한 CSS를 미리 생성해 줍니다. 무엇보다 폰트 로딩 시 발생하는 레이아웃 시프트(CLS) 현상을 방지해주기 때문에 성능적으로 좋은 효과를 가질 수 있다.
내부 폰트 설정: Google Fonts (Fira Code)#
코드 영역에 적용할 Fira Code를 가져와 보자. 이 폰트는 Google Fonts에서 제공하므로, 파일을 따로 다운로드할 필요 없이 next/font/google을 통해 간편하게 불러올 수 있다.
// src/fonts/index.ts
import { Fira_Code } from 'next/font/google';
export const firaCode = Fira_Code({
subsets: ['latin'],
weight: ['400', '500', '600', '700'],
display: 'swap',
variable: '--font-fira-code',
});외부 폰트 설정: Local Fonts (Pretendard)#
본문에 사용할 Pretendard는 로컬 폰트 방식으로 설정한다. 확인해보니 Variable 폰트 파일의 경우 용량이 약 3MB에 달하는데, 웹 환경에는 조금 부담스러운 크기라고 생각한다.
그래서 성능을 위해 전체 폰트 대신 필요한 글자만 담은 Subset 파일(woff2) 을 사용하는 것을 권장한다.
사용하고 싶은 서브셋 폰트들을 프로젝트 내부 경로로 위치시키자.
src
└── fonts
├── Pretendard-Bold.subset.woff2
├── Pretendard-Medium.subset.woff2
├── Pretendard-Regular.subset.woff2
├── Pretendard-SemiBold.subset.woff2
└── index.ts그 후 next/font/local을 이용해 아래와 같이 정의한다.
// src/fonts/index.ts
import localFont from 'next/font/local';
export const pretendard = localFont({
src: [
{
path: './Pretendard-Regular.subset.woff2',
weight: '400',
},
{
path: './Pretendard-Medium.subset.woff2',
weight: '500',
},
{
path: './Pretendard-SemiBold.subset.woff2',
weight: '600',
},
{
path: './Pretendard-Bold.subset.woff2',
weight: '700',
},
],
display: 'swap',
variable: '--font-pretendard',
});폰트 적용#
이제 정의한 폰트들을 컴포넌트에 적용해 보자. 상황에 따라 아래 중 가장 괜찮은 방식을 선택해 사용하면 좋을 것 같다.
1. 컴포넌트 수준에서 적용 (className)
가장 간단한 방법으로, Next.js 폰트 객체에서 제공하는 className 속성을 사용하는 방식이다. 특정 컴포넌트나 레이아웃에만 폰트를 입히고 싶을 때 유용하다.
import { pretendard } from '@/fonts';
export default function Intro() {
return (
<section className={pretendard.className}>
<h1>폰트가 적용된 소개 페이지</h1>
</section>
);
}2. CSS 스타일 시트에서 활용 (CSS Variable)
next/font 설정 시 지정했던 variable 값을 이용해 일반 CSS 파일이나 Inline Style에서 활용하는 방식이다.
/* globals.css */
.custom-title {
font-family: var(--font-pretendard);
font-weight: 700;
}
code {
font-family: var(--font-fira-code);
}3. Tailwind v4와 연동하여 활용
Tailwind v4에서는 메인 CSS 파일(globals.css)에서 변수를 직접 매핑하는 방식을 사용한다. 먼저 폰트 변수를 최상위 태그에 주입한다.
// src/pages/_app.tsx
<html lang="ko" className={`${pretendard.variable} ${firaCode.variable}`}>그 후, CSS 파일에서 @theme 블록을 이용해 기본 font-family를 우리가 정의한 폰트로 덮어씌운다.
/* src/styles/globals.css */
@import 'tailwindcss';
@theme {
/* --font-pretendard 변수를 Tailwind의 sans 폰트로 지정 */
--font-sans: var(--font-pretendard);
/* --font-fira-code 변수를 Tailwind의 mono 폰트로 지정 */
--font-mono: var(--font-fira-code);
}이렇게 설정하면 별도의 스크립트 설정 없이도, 프로젝트 전체에서 font-sans(기본)와 font-mono(코드 영역) 클래스를 사용할 때 우리가 설정한 최적화된 폰트를 적용할 수 있다.
📌 주의: Tailwind 테마 변수와 일반 CSS 변수의 차이
Tailwind v4의
@theme내부에 정의한--font-sans같은 값들은 Tailwind 내부의 유틸리티 클래스를 생성하기 위한 용도다. 따라서 일반 CSS 파일에서var(--font-sans)를 직접 사용하면 브라우저가 인식하지 못할 수 있다.
마무리#
폰트 설정을 마치며 느낀 점은, 블로그의 전반적인 스타일은 Tailwind CSS로 제어하고 마크다운 본문은 일반 CSS로 관리하다 보니 스타일 정의가 이원화되는 느낌이 들었다.
이를 좀 더 깔끔하게 관리할 수 있는 방법을 한 번 찾아봐야겠다.