์ด๋ฒ ๊ธ์์๋ Next.js 14 ๋ฒ์ ์์ Pretendard ํฐํธ๋ฅผ ์ ์ฉํ๋ ๋ฒ๊ณผ, ๊ธฐ์กด์ cdn์์ ํฐํธ๋ฅผ ์ ์ฉํ๋ ๊ฒ์ ๋นํด์ ์ด๋ค ์ต์ ํ๊ฐ ์ด๋ฃจ์ด์ง๋์ง ๋ค๋ฃจ๊ฒ ์ต๋๋ค. ํ์ฌ Next.js 14์ ๋ํ ์๋ฃ๋ ํ๊ธํ๋ ๋ฌธ์๊ฐ ๋ง์ง ์์์ ๋์์ ๋ฐ์ผ์ค ๋ถ๋ค์ด ๋ง์ผ์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
Pretenard
- ์ฌ์ค์ ํ์ ํ์ค์ผ๋ก ์๋ฆฌ์ก์ ํ๊ธ ํฐํธ์ ๋๋ค. ์ฌ๋ฌ ํ์ฌ๋ค์ด ํ๋ก์ ํธ์ ์ ์ฉํ๊ณ ์์ต๋๋ค.
- ์์ด์ฝ, ์ซ์์์ ๋ฐฐ์น๊ฐ ์์ฐ์ค๋ฌ์ด ๊ฒ์ด ์ฅ์ ์ ๋๋ค.
- ํฐํธ ๊ตต๊ธฐ๊ฐ ๋ค์ํ์ฌ ์ฌ์ธํ ํฐํธ ์คํ์ผ๋ง์ด ๊ฐ๋ฅํฉ๋๋ค.
- ๋ฌด๋ฃ ์์ ์ฉ ํฐํธ๋ก ๋๊ตฌ๋ ๊ฐ์ ธ๋ค ์ธ ์ ์์ต๋๋ค.
์ค์น
-
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> ); }
tailwindcss์ css varaible๋ก ๋ฑ๋กํ๊ณ ์ฌ์ฉํ๊ธฐ
์ ์ญ์ ์ผ๋ก ํฐํธ๋ฅผ ์ ์ฉ์ํค๋ ๋์ ์ ๋ถ๋ถ์ ์ผ๋ก ํฐํธ๋ฅผ ์ ์ฉํ๊ณ ์ถ์ ๋๋ 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>
Font Optimization
์ด ์ฏค์์ ์๋ฌธ์ด ๋ค์์ต๋๋ค.
.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๋ฅผ ํ์ธํ์ต๋๋ค.
ํ์ด์ง์ ์ ์ํ์ ๋ ์ฒ์ ๋ฐ์์ค๋ global css file์ ํ์ธํด๋ณด๋, ์ปค์คํ ํฐํธ๊ฐ ๋ก๋๋๋ ๋์ fallback font์
size-adjust
๋ฅผ ์ค์ ํ์ฌ layout shift๋ฅผ ๋ง๊ณ ์์์ต๋๋ค.