Next.js 언어별 폰트 적용하기 - @font-face
📌시작하며
이번에 진행하는 프로젝트에서 전부터 해보고 싶었던 ‘언어 변경’기능을 구현하고 있다. 한국어와 일본어 두 언어를 지원하는 애플리케이션인데, 각 언어에 적절한 font를 사용하고 싶어 방법을 검색해보게 되었다.
🤔 Next/font를 시도하다
이번 프로젝트에서는 Next13을 사용하고 있고, Next.js가 13으로 업데이트되면서 새로 제공하는 Next/font 기능을 활용하려고 의욕이 가득찼었으나.. 문제가 발생했다!
한국어와 일본어 모두 Noto Sans를 사용할 계획이었고, 일단 아래와 같이 layout.tsx
에서 아래와 같이 작성해주었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { Noto_Sans_KR } from "next/font/google"
import { Noto_Sans_JP } from "next/font/google"
const notoKR = Noto_Sans_KR({ subsets: ["latin"], variable: "--ko" })
const notoJP = Noto_Sans_JP({ subsets: ["latin"], variable: "--jp" })
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="ko" className={`${notoKR.variable} ${notoJP.variable}`}>
<body>{children}</body>
</html>
)
}
이후 tailwind에서도 사용하기 위해서, tailwind.config.ts
파일에 다음과 같이 variable을 적용해주었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const config: Config = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
fontFamily: { 👈
ko: ['var(--ko)'],
jp: ['var(--jp)'],
},
},
},
};
그리고 실제 사용할 때는 font-ko
, font-jp
를 이용해 각각 적용할 수 있었다.
😥 하지만(…)
여기까지는 Next13을 이용해 여러 font를 등록하고 tailwind와 함께 사용할 수 있는 유용한 방법이지만 문제는 내가 원한 작동방식이 이게 아니라는 거다. recoil을 이용해 사용자가 언어를 변경했을 때 각 언어별로 자동으로 다른 font가 적용되어야 하는데 위의 방식은 현재 language에 따라 적용할 언어를 따로따로 적어주어야 했다.
시도해봤으나, 너무 번거롭고, 한국어와 일본어가 섞인 문장이 등장할 수 있어, 이 경우에는 처리하기 막막했다. 다른방법을 찾아야 했다.
✅ @font-face 사용법
결국 다른 방법이 필요했고, 구글링💻을 통해 같은 문제를 겪고계신 개발자 분을 발견했고, 그 질문에 대한 답변으로 font-face와 unicode-range를 사용하는 방법을 알게 되었다.
font-face
는 아래와 같은 속성값을 이용해 웹페이지의 텍스트에 개발자가 원하는 폰트를 적용할 수 있는 CSS 기술이다. 여기서 내가 원하는 기능은 unicode-range
를 이용해 구현할 수 있었다.
1
2
3
4
5
6
7
@font-face {
font-family: <a-remote-font-name>; //마음대로 지정해도 됨
src: <source> [,<source>]*; //font가 있는 url 혹은 파일 지정
[font-weight: <weight>]; //특정 weight를 지정할 수 있음
[font-style: <style>];
[unicode-range: ~ ] // 해당 폰트가 적용될 unicode 범위 작성
}
언어 | 유니코드 |
---|---|
한국어 | U+AC00-U+D7AF |
영어(대문자) | U+0041-U+005A |
영어(소문자) | U+0061-U+007A |
일본어(ひらがな) | U+3040-U+309F |
일본어(カタカナ) | U+30A0-U+30FF |
일본어(漢字) | U+4E00-U+9FFF |
숫자 | U+0030-U+0039 |
✅ 적용한 CSS
최종적으로 아래와 같이 global.css
에서 다음과 같이 @font-face를 작성했다. 일본어 unicode가 많아 번거로워, 한글 font에 unicode-range를 적용해주었다.
1
2
3
4
5
6
7
8
9
10
@font-face {
font-family: "noto";
src: url("../../public/font/NotoSansJP-VariableFont_wght.ttf") format("truetype");
}
@font-face {
font-family: "noto";
src: url("../../public/font/NotoSansKR-VariableFont_wght.ttf") format("truetype");
unicode-range: U+AC00-D7A3; 👈
}
이후 layout.tsx
에서 이렇게 만든 font-face를 적용하겠다고 작성해주었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="ko">
<head />
<body className={`font-[noto]`}👈>
<div className="flex min-h-screen flex-col ">{children}</div>
</body>
</html>
)
}
이제 각 언어별로 원하는 font가 제대로 적용되었다!
📩마무리
font도 적용되었으니 이제 열심히 언어 json 파일을 만들어보자!