NextJS로 블로그를 만들고 있는데 Tailwind CSS만으로는 전역 폰트 설정이 되지 않는 문제가 생겼다. 알고보니 Next에 기본적으로 폰트가 설정되어 있었고 css로 body에 폰트를 적용해도 덮어씌워지지 않았다. Next.js의 폰트 최적화에 대해 알아보고 동시에 전역 폰트 설정을 해보자.
NextJS의 폰트 최적화
NextJS에서는 기본적으로 next/font를 사용한 폰트 최적화 기능을 제공한다. npx create-next-app을 했을 때 기본 layout.tsx파일을 확인해보면 아래와 같이 설정되어 있다.
import type { Metadata } from "next";
import localFont from "next/font/local";
import "./globals.css";
const geistSans = localFont({
src: "./fonts/GeistVF.woff",
variable: "--font-geist-sans",
weight: "100 900",
});
const geistMono = localFont({
src: "./fonts/GeistMonoVF.woff",
variable: "--font-geist-mono",
weight: "100 900",
});
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
{children}
</body>
</html>
);
}
layout.tsx에는 next/font를 사용해 저장된 로컬 폰트를 적용하는 예시를 보여준다. 공식 문서에 나와있다시피 next/font는 모든 글꼴 파일에 대해 자동으로 자체 호스팅되는 기능이 내장되어 있다. 즉, 사용된 폰트는 빌드 타임에 다운로드 하여 다른 정적 자산과 함께 호스팅하므로 외부 네트워크 요청을 줄일 수 있다. 이것을 가능하게 한 것은 바로 css의 size-adjust속성 덕분이다. 이 속성이 next/font에 내장되어 있어 사용자는 방문할 때마다 매번 폰트를 다운로드 하지 않아도 되므로 성능 최적화에 유용하다.
이 부분을 변경하지 않고 globals.css에 body의 폰트를 변경했으나 변경된 폰트가 적용되지 않았다. 이는 이미 layout.tsx의 body태그에 폰트 변수가 className으로 추가되어 있어서이다. 클래스 선택자의 우선순위가 태그 선택자보다 높기 때문에 body태그에 font를 지정해도 className으로 지정된 폰트가 우선순위가 높아 변경되지 않는 것이었다.
import { Roboto, Oswald } from "next/font/google";
const roboto = Roboto({
subsets: ["latin"],
weight: "400",
variable: "--font-roboto",
});
const oswald = Oswald({ subsets: ["latin"], variable: "--font-oswald" });
...
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={`${roboto.className} ${oswald.variable}`}>
<Navigation />
<main>{children}</main>
</body>
</html>
);
}
따라서 layout.tsx에서 폰트를 변경해준다. 로컬에 저장된 폰트를 사용하는 것 말고도 next/font를 활용해 구글 폰트를 가져올 수도 있다. 나는 roboto와 oswald 구글 폰트가 필요했기 때문에 이 두 폰트를 불러와서 변수에 담아 사용했다.
subsets옵션
subsets은 해당 글꼴에 대해 미리 로드할 하위 집합을 지정하는 것이므로, 없다면 오류를 내뱉는다. 만약 하위 집합으로 지정하지 않고 오류를 없애려면 폰트 옵션에 preload: false를 추가해 미리 로드하는 것을 막을 수 있다.
subsets의 옵션에는 korean은 없는데 보통 폰트로 영어를 사용하는 일도 많으므로 latin으로 지정하여 미리 로드를 한다. 이외에도 미리 로드할 필요가 있는 언어가 있다면 배열 형태로 넣을 수 있다.
weight옵션
폰트의 두께를 배열로 설정한다. 모든 폰트의 두께가 아닌 사용하는 폰트 두께만 가져오므로 더 효율적으로 사용할 수 있다. 이 값은 가변 폰트(Variable Font)가 아니면 필수로 넣어줘야 한다. 내가 사용한 oswald폰트는 가변폰트여서 weight가 필요없지만, roboto폰트는 가변폰트가 아니므로 wegith옵션을 넣지 않으면 오류가 발생한다.
구글 폰트 중에 가변 폰트인지 아닌지는 여기서 확인할 수 있다.
💡가변 폰트(Variable Font)란?
가변 폰트(Variable Font)는 한 개의 폰트 파일 안에 여러 개의 스타일을 담을 수 있는 기술이다. 일반적으로 폰트는 여러 개의 별도 파일로 제공되며, 각각의 파일은 다른 스타일를 담고 있다. 예를 들어, 'Regular', 'Medium', 'Bold'과 같은 여러 형태의 폰트가 각각 별도의 파일로 제공되었고, 이는 애플리케이션을 개발할 때 여러 폰트 파일을 관리하고 불러와야 하는 번거로움을 가져왔다. 가변 폰트는 이런 문제를 해결하고자 만들어진 개념이다. 원하는 두께나 스타일을 프로그래밍적으로 선택할 수 있다. 이를 통해 여러 폰트 파일 관리의 번거로움이 줄어들고 데이터의 크기와 다운로드 시간을 줄일 수 있다.
variable 옵션
css 변수를 설정하여 해당 변수를 다른 css파일에 적용할 수 있는 옵션이다. 예를 들어 아래와 같이 roboto폰트에 css변수명으로 --font-roboto를 설정했다면 다른 css파일에서 해당 변수를 사용할 수 있다.
import { Roboto, Oswald } from "next/font/google";
const roboto = Roboto({
subsets: ["latin"],
weight: "400",
variable: "--font-roboto",
});
const oswald = Oswald({ subsets: ["latin"], variable: "--font-oswald" });
...
return <body className={`${roboto.className} ${oswald.variable}`}>...</body>
// globals.css
.test{
font-family: var(--font-roboto);
font-weight: 200;
font-style: italic;
}
roboto폰트는 전역에서 사용할 것이므로 className으로 폰트가 전역에서 사용되도록 해주었고, oswald폰트는 변수만 전달하여 필요한 부분에서 사용하려 한다.
Tailiwind CSS와 함께 전역 폰트 설정하기
레이아웃에는 위와 같이 구글 폰트를 가져와서 body에 전달을 했다. 이제 tailwind css로 해당 폰트들을 사용하기 위해 먼저 tailwind.config.ts에 아래와 같이 설정한다.
import type { Config } from "tailwindcss";
const config: Config = {
...
theme: {
extend: {
fontFamily: {
roboto: ["var(--font-roboto)"],
oswald: ["var(--font-oswald)"],
},
},
},
...
};
이미 variable옵션으로 이름을 설정해놨으므로 fontFamily에는 roboto와 oswald폰트를 추가하고 알맞은 css variable을 작성한다. roboto폰트는 className으로 전달한 덕분에 기본적으로 모든 곳에 적용되었으나 혹시 모를 상황을 대비해서 함께 설정해놓았다. 이제 태그 내 클래스네임으로 font-roboto 또는 font-oswald를 작성해 폰트를 지정할 수 있다.
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
color: var(--foreground);
background: var(--background);
}
h1,
h2,
h3 {
@apply font-oswald;
}
globals.css에는 위와 같이 @apply를 사용해 h1, h2, h3 태그에만 font-oswald를 적용했다. 시맨틱 마크업을 할 것이므로 제목이 되는 부분에는 oswald폰트를 사용할 예정이다.
<p className="font-oswald text-gray-200 w-11/12 max-w-xl m-auto">
이외에도 다른 곳에 필요하다면 언제든지 클래스네임으로 폰트를 설정할 수 있다.
Reference
'개발 > 프론트엔드' 카테고리의 다른 글
[NextJS] GIF는 Image컴포넌트의 최적화가 지원되지 않는다?! (feat. Cloudinary) (0) | 2024.10.17 |
---|---|
[CI/CD]vercel에 무료로 organization레포지토리 배포하기 (0) | 2024.09.26 |
[Typescript] 타입스크립트는 왜 쓰는걸까? (4) | 2024.09.05 |
[React] 리액트로 스톱워치 Chrome Extension 만들기 (0) | 2024.08.29 |
[NextJS]App Router - 앱 최적화와 캐싱 (0) | 2024.08.01 |