먼저 폰트를 적용한 프로젝트의 기술 버전은 다음과 같습니다.
- Next.js 15 (Page Router)
- Tailwind v4
- Typescript 5
💬 폰트 파일 다운로드하기
제가 사용할 폰트는 'Pretendard'와 '이롭게 바탕체'였습니다.
공식 사이트에서 웹 폰트를 다운로드하고, 'woff' 파일을 프로젝트에 추가합니다.
저는 다음과 같은 폴더 구조로 폰트 파일을 저장했습니다. (./src/assets/fonts)
💬 localFont 불러오기
프로젝트의 뼈대가 되는 '_app.tsx' 파일에 Next.js의 'next/font' 모듈을 임포트 하고 폰트를 로드합니다.
import localFont from 'next/font/local';
// 프리텐다드 폰트
const pretendard = localFont({
src: '../assets/fonts/PretendardVariable.woff2',
display: 'swap',
weight: '100 900',
variable: '--font-pretendard',
});
// 이롭게 바탕체 폰트
const batang = localFont({
src: '../assets/fonts/IropkeBatangM.woff',
display: 'swap',
weight: '100 900',
variable: '--font-batang',
});
localFont 각 속성의 의미는 다음과 같습니다.
- src
- 폰트 파일의 경로입니다. localFont에서만 사용되는 속성으로 폰트 로더 함수가 호출되는 디렉터리를 기준으로 합니다.
- 경우 1) src 폴더 안에 저장되어 있을 때
- 저는 폰트 파일을 src/assets/fonts 폴더에 저장해 두고 src/pages/_app.tsx 파일에서 불러왔기 때문에 경로를 '../assets~'로 작성했습니다.
- 경우 2) public 폴더 안에 저장되어 있을 때
- 만약 public/fonts 폴더에 폰트 파일을 저장해 두고 불러올 때 '/fonts/PretendardVariable.woff2'처럼 절대 경로를 사용했는데 폰트 적용이 되지 않는다면 절대 경로가 아닌 상대 경로로 바꿔보시길 바랍니다.
- '../../public/fonts/PretendardVariable.woff2'이렇게 바꿨더니 제대로 적용되었습니다.
- display
- 폰트가 보이는 방식입니다.
- 기본값은 'swap'으로, 폰트가 로드되지 않았다면 대체 폰트로 보여준 뒤, 폰트가 로드되면 원래 폰트로 변환하는 방식입니다.
- weight
- 폰트의 굵기 값입니다.
- 가변 폰트라면 위와 같이 범위로 설정할 수 있습니다. '100 900'은 100~900 사이를 의미합니다.
- 비가변 폰트라면 가능한 굵기 값의 배열로 설정할 수 있습니다.
- variable
- 폰트를 css 변수로 정의합니다.
- 폰트를 적용하기 위해서 variable로 정의한 변수를 _app 파일에서 className으로 적용해줍니다.
- 경우 1) 전역으로 적용 시에는 className={폰트.className}로 지정할 수 있습니다.
- 경우 2) 부분으로 적용 시에는 className={폰트.variable}로 지정할 수 있습니다.
- 아래의 컴포넌트 적용 코드에 자세히 나와있습니다.
더 많은 속성들은 공식 문서를 참고해 주세요.
원하는대로 설정해 주었다면 폰트를 컴포넌트에 적용합니다.
export default function App({ Component, pageProps }: AppProps) {
return (
<main className={`${pretendard.className} ${batang.variable}`}>
<Component {...pageProps} />
</main>
);
}
전역으로(기본 폰트) 적용할 폰트는 .className으로, 부분적으로 css 속성을 통해 적용할 폰트는 .varible로 지정합니다.
_app.tsx의 전체 코드는 다음과 같습니다.
import '@/styles/globals.css';
import type { AppProps } from 'next/app';
import localFont from 'next/font/local';
const pretendard = localFont({
src: '../assets/fonts/PretendardVariable.woff2',
display: 'swap',
weight: '100 900',
variable: '--font-pretendard',
});
const batang = localFont({
src: '../assets/fonts/IropkeBatangM.woff',
display: 'swap',
weight: '100 900',
variable: '--font-batang',
});
export default function App({ Component, pageProps }: AppProps) {
return (
<main className={`${pretendard.className} ${batang.variable}`}>
<Component {...pageProps} />
</main>
);
}
💬 Tailwind CSS에 적용하기
tailwind v4부터는 tailwind.config.js 파일을 사용하지 않으므로 다음과 같이 global.css 파일에 @theme으로 css 변수를 추가해 줍니다.
@import 'tailwindcss';
@theme {
--font-pretendard: 'Pretendard Variable', 'sans-serif';
--font-batang: 'IropkeBatangM', 'serif';
}
tailwind v3에서의 적용 방식은 공식 문서를 참고해 주세요.
💬 컴포넌트에 적용하기
전역 폰트로 설정한 Pretendard는 따로 지정해주지 않아도 적용되고, 두 번째 div에만 className으로 이롭게 바탕체를 적용했습니다.
export default function Home() {
return (
<>
<div>이건 Pretendard</div>
<div className="font-batang">이건 Iropke Batang</div>
</>
);
}
크롬의 개발자 도구로 확인해 보면 폰트가 잘 적용된 것을 볼 수 있습니다.
tailwind가 v4로 업데이트되고 나서 달라진 것이 많다는 걸 느꼈습니다.
next.js의 폰트 최적화를 적용해 보기 위해 next/font 모듈을 처음 써보았는데,
블로그마다 설명하고 있는 기술 버전이 제각각이라 한 번에 성공하지 못해 폰트 적용조차 헤매는 건가 라는 생각을 하기도 했습니다.
결국 정답은 공식 문서였고, 영어로 되어 있더라도 겁먹지 말고 한 단계씩 따라 해 보는 것이 중요하다는 것을 깨달았습니다.
앞으로는 새 기술을 적용할 때 공식 문서를 우선적으로 확인하고 버전을 체크하는 습관을 들이려고 합니다.
각각 Next.js, TailwindCSS 공식 문서입니다.
읽어주셔서 감사합니다:)