์ด๋ฒ ๊ธ์์๋ Next.js 14 ๋ฒ์ ์์ Pretendard ํฐํธ๋ฅผ ์ ์ฉํ๋ ๋ฒ๊ณผ, ๊ธฐ์กด์ cdn์์ ํฐํธ๋ฅผ ์ ์ฉํ๋ ๊ฒ์ ๋นํด์ ์ด๋ค ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๋์ง ๋ค๋ฃจ๊ฒ ์ต๋๋ค. ํ์ฌ Next.js 14์ ๋ํ ์๋ฃ๋ ํ๊ธํ๋ ๋ฌธ์๊ฐ ๋ง์ง ์์์ ๋์์ ๋ฐ์ผ์ค ๋ถ๋ค์ด ๋ง์ผ์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
- Pretenard
- ์ค์น
- tailwindcss์ css varaible๋ก ๋ฑ๋กํ๊ณ ์ฌ์ฉํ๊ธฐ
- Font Optimization
- References
- ์ฌ์ค์ ํ์ ํ์ค์ผ๋ก ์๋ฆฌ์ก์ ํ๊ธ ํฐํธ์ ๋๋ค. ์ฌ๋ฌ ํ์ฌ๋ค์ด ํ๋ก์ ํธ์ ์ ์ฉํ๊ณ ์์ต๋๋ค.
- ์์ด์ฝ, ์ซ์์์ ๋ฐฐ์น๊ฐ ์์ฐ์ค๋ฌ์ด ๊ฒ์ด ์ฅ์ ์ ๋๋ค.
- ํฐํธ ๊ตต๊ธฐ๊ฐ ๋ค์ํ์ฌ ์ฌ์ธํ ํฐํธ ์คํ์ผ๋ง์ด ๊ฐ๋ฅํฉ๋๋ค.
- ๋ฌด๋ฃ ์์ ์ฉ ํฐํธ๋ก ๋๊ตฌ๋ ๊ฐ์ ธ๋ค ์ธ ์ ์์ต๋๋ค.
- Prendtendard releast note๋ก ๋ค์ด๊ฐ์ ํ์ผ์ ๋ค์ด๋ก๋ ๋ฐ์์ฃผ์ธ์.

- ์์ถ์ ํ๊ณ
.../Pretendard-1.3.9/web/variable/woff2/PretendardVariable.woff2
ํ์ผ์ ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ์ ๋ฃ์ด์ฃผ์ธ์. ์ ํ๋ก์ ํธ์๋ /static/fonts ๋๋ ํ ๋ฆฌ์ ๋ฃ์์ต๋๋ค.

-
global font๋ก ์ ์ฉ์ํค๊ธฐ ์ํด์
app/layout.tsx
์ className์ ์ ๋ฌํฉ๋๋ค.import localFont from "next/font/local"; const pretendard = localFont({ src: "../static/fonts/PretendardVariable.woff2", display: "swap", weight: "45 920", variable: "--font-pretendard", }); export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="kr" className={`${pretendard.variable}`}> <body className={pretendard.className}> <Header /> {children} </body> </html> ); }
์ ์ญ์ ์ผ๋ก ํฐํธ๋ฅผ ์ ์ฉ์ํค๋ ๋์ ์ ๋ถ๋ถ์ ์ผ๋ก ํฐํธ๋ฅผ ์ ์ฉํ๊ณ ์ถ์ ๋๋ tailwind์ css variable์ผ๋ก ๋ฑ๋กํ ์ ์์ต๋๋ค.
-
app/layout.tsx
์์ ํฐํธ์ css variable์ document์ ๋ฃ์ด์ค๋๋ค.import localFont from "next/font/local"; const pretendard = localFont({ src: "../static/fonts/PretendardVariable.woff2", display: "swap", weight: "45 920", variable: "--font-pretendard", }); export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( <html lang="kr" className={`${pretendard.variable}`}> <body className={pretendard.className}> <Header /> {children} </body> </html> ); }
-
tailwind.cssconfig.js
์์ css variable์ ์ถ๊ฐํฉ๋๋ค.
import type { Config } from "tailwindcss";
const config: Config = {
content: [
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./src/**/*.{js,ts,jsx,tsx,mdx}",
"./stories/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
fontFamily: {
pretendard: ["var(--font-pretendard)"],
},
},
},
plugins: [],
};
export default config;
className
์ font-pretendard
๋ฅผ ์ถ๊ฐํ์ฌ ํฐํธ๋ฅผ ์ ์ฉ์ํฌ ์ ์์ต๋๋ค.
<div className="font-pretendard shrink-0 font-black">ํ๋ฆฌํ
๋ค๋</div>
์ด ์ฏค์์ ์๋ฌธ์ด ๋ค์์ต๋๋ค.
.css file์์
font-face
attribute๋ก cdn ํตํด ํฐํธ๋ฅผ ๋ค์ด๋ก๋ ๋ฐ์ง ์๊ณ ๊ตณ์ด ์ด๋ ๊ฒ ๊ตฌํํด์ผ ํ๋ ์ด์ ๊ฐ ๋ฌด์์ผ๊น?
Next.js ํํ ๋ฆฌ์ผ ๋น๋์ค์ ๋ฐ๋ฅด๋ฉด ์ด์ ๋ํด ๋ค์๊ณผ ๊ฐ์ด ๋ต๋ณํด์ค๋๋ค.
-
cdn์ผ๋ก๋ถํฐ ๋ค์ด๋ก๋ ๋ฐ๊ฒ ๋๋ ๊ฒฝ์ฐ์๋ ํด๋ผ์ด์ธํธ์์ custom ํฐํธ๋ฅผ ๋ค์ด๋ก๋ ๋ฐ๊ธฐ ์ ๊น์ง๋ ์ด์์ฒด์ ์์ ์ฌ์ฉ ๊ฐ๋ฅํ fallback font(Arial ๋ฑ)๋ฅผ ์ฌ์ฉํ๊ฒ ๊ฒ ๋ฉ๋๋ค. custom ํฐํธ ๋ก๋ ์ /๋ก๋ ํ์ ํฐํธ ์ฌ์ด์ฆ ํฌ๊ธฐ ์ฐจ์ด๋ก ์ธํด cumulative layout shift๊ฐ ๋ฐ์ํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ํฌ๊ฒ ๋จ์ด๋จ๋ฆฌ๊ฒ ๋ฉ๋๋ค.
-
Next.js
์next/font
๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์๋ font๋ฅผ ๋น๋ ํ์ ๋ ํ๋ฒ๋ง ๋ค์ด๋ก๋ ๋ฐ๊ณ , fallback font๊ฐ ์ฌ์ฉ๋๋ ๋์ csssize-adjust
ํ๋กํผํฐ๋ฅผ ์ ์ฉ์์ผ์ ๊ธ์ ํฌ๊ธฐ๋ฅผ ๋์ผํ๊ฒํ์ฌ layout shift๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ๋ง์์ค๋๋ค.
์ง์ ๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ผ๊ณ ํ์ธํด๋ดค์ต๋๋ค. ๋คํธ์ํฌ์ throttling์ ๊ฑธ์ด์ ์ผ๋จ custom font๊ฐ ๋ก๋๋๊ธฐ ์ ์ UI์ ๋ก๋๋ ํ์ UI๋ฅผ ํ์ธํ์ต๋๋ค.
-
๋ก๋ ์ : ์์คํ ํฐํธ๊ฐ ์ ์ฉ๋์์ต๋๋ค.
-
๋ก๋ ํ: Pretendard ํฐํธ๊ฐ ์ ์ฉ๋์์ต๋๋ค.
-
ํ์ด์ง์ ์ ์ํ์ ๋ ์ฒ์ ๋ฐ์์ค๋ global css file์ ํ์ธํด๋ณด๋, ์ปค์คํ ํฐํธ๊ฐ ๋ก๋๋๋ ๋์ fallback font์
size-adjust
๋ฅผ ์ค์ ํ์ฌ layout shift๋ฅผ ๋ง๊ณ ์์์ต๋๋ค.

