Post

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 파일을 만들어보자!

🗂️참고 사이트

This post is licensed under CC BY 4.0 by the author.