여러 클론코딩 사이트를 하나에 모아두려는 프로젝트를 하려는 중에
웹폰트랑 로컬폰트를 둘 다 적용할 일이 있어서 알아보다가 기록해두는 글
루트에선 Next.js에서 기본으로 제공하는 구글 웹폰트를 사용하고,
클론코딩 할 폴더에선 나눔스퀘어 글꼴을 따로 적용해야하는 상황이었다.
처음엔 루트와 클론 폴더 모두에 layout.tsx를 만들고 적용하려니 오류가 나타났다.
A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used
알아보니 웹폰트와 로컬폰트를 동시에 불러오는 과정에서 Next.js hydration mismatch이 일어나는 것.
그때의 코드
// app폴더의 layout.tsx
import { Noto_Sans_KR } from "next/font/google";
import "./globals.css";
const notoSansKR = Noto_Sans_KR({
weight: ["300", "400", "700"],
variable: "--font-noto-sans-KR",
subsets: ["latin"],
});
function Layout({ children }: { children: React.ReactNode }) {
return (
<html
lang="ko-KR"
className={`${notoSansKR.variable}`}
>
<body>{children}</body>
</html>
);
}
export default Layout;
// app/maeil폴더의 layout.tsx
import localFont from "next/font/local";
import "./app.css";
import Header from "./components/Header";
const nanumSqure = localFont({
src: "./font/NanumSquareR.ttf",
display: "swap",
});
function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko-KR" className={`${nanumSqureFont.className}`}>
<body>
<Header />
{children}
</body>
</html>
);
}
export default Layout;
첨에 채찌피티가 저렇게 하면 html태그가 따로 적용된다 해서 철썩같이 믿은게 화근 아오ㅡㅡ
루트의 html 밑에 또 html을 만들려고 하니 당연히 오류가 생기는 것이었다.
결국 하위 layout.tsx에서 html이나 body 태그를 떼고 div로 감싸서 적용하니 잘 됨.
이때 폰트 파일은 적용할 폴더에 함께 넣어줘야 한다.
import localFont from "next/font/local";
import "./app.css";
import Header from "./components/Header";
const nanumSqure = localFont({
src: [
{
path: "./fonts/NanumSquareL.ttf",
weight: "300",
},
{
path: "./fonts/NanumSquareR.ttf",
weight: "400",
},
{
path: "./fonts/NanumSquareB.ttf",
weight: "700",
},
],
fallback: ["system-ui", "arial"],
});
function Layout({ children }: { children: React.ReactNode }) {
return (
<div className={`${nanumSqure.className}`}>
<Header />
{children}
</div>
);
}
번외로,
폰트를 적용할 때, 한글은 Noto Sans KR, 영어 및 숫자는 Monserrat를 적용하는 것을 좋아하는데, 루트에서 적용해보기로 한다.
import { Noto_Sans_KR, Montserrat } from "next/font/google";
import "./globals.css";
const notoSansKR = Noto_Sans_KR({
weight: ["300", "400", "700"],
variable: "--font-noto-sans-KR",
subsets: ["latin"],
});
const montserrat = Montserrat({
weight: ["300", "400", "700"],
variable: "--font-montserrat",
subsets: ["latin"],
});
function Layout({ children }: { children: React.ReactNode }) {
return (
<html
lang="ko-KR"
className={`${montserrat.variable} ${notoSansKR.variable}`}
>
<body>{children}</body>
</html>
);
}
export default Layout;
이렇게 적어두고 gloabal.css에도 따로 font-family를 적용해주어야 한다. 순서는 영문, 숫자폰트 먼저.
이유는 폰트가 적용될 때 앞에 써져있는 폰트부터 우선 적용되기 때문이다.
한글 폰트를 앞에 적어두면 영어, 숫자가 한글 폰트에 있던 것이 적용되어 Montserrat가 적용될게 없기때문에
영어, 숫자 폰트만 있는 Montserrat를 먼저 적용하고 남은 한글 폰트에 Noto Sans KR을 적용하는 것.
body {
background: var(--background);
color: var(--foreground);
font-family: var(--font-montserrat), var(--font-noto-sans-KR), sans-serif;
}
아주 잘 적용 됨! 굿!