새로운 font를 추가하여 사용하기 위해선 대표적으로 두 가지 방법이 있다. 예를 들어 google font 중 Oswald font를 사용하고 싶다고 가정해보자.
첫 번째 방법은 remote server로 사용하고자 하는 font를 요청하고 해당 font를 적용하기 위한 class name을 생성하여 적용한다.
<head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
href="https://fonts.googleapis.com/css2?family=Oswald:wght@200..700&display=swap"
rel="stylesheet"
/>
</head>
.oswald {
font-family: "Oswald", sans-serif;
}
<div class="oswald">Test Font 123</div>
하지만 위의 방법은 사이트를 처음 접근할 때 font를 remote server로 요청해 가져올 동안 default font가 사용되고 request가 완료되고 나서야 비로서 google font가 적용되기에 network 상태가 좋지 않은 환경에서 사이트에 접근한다면 font family 변경으로 인한 layout shift가 확연하게 나타난다.
두 번째 방법은 사용하는 font를 project local에 저장해두고 @font-face
를 통해 해당 font를 선언하여 사용하는 방법이다.
// global.css
@font-face {
font-family: "Oswald";
font-weight: 400;
font-style: normal;
src: url("/public/fonts/Oswald/Oswald-Regular.ttf") format("truetype");
}
.oswald {
font-family: "Oswald", sans-serif;
}
<div class="oswald">Test Font 123</div>
NextJS가 제공하는 next/font
module을 통해 기본적으로 google font에서 제공하는 font를 사용할 수 있다. 그리고 해당 module을 통해 font를 사용하면 build시 사용하는 font를 local에 설치하여 위와 같은 방법을 통해 font를 제공한다.
NextJS가 제공하는 next/font
module 사용법을 살펴보기 전 @font-face
syntax를 살펴보자.
만약 next/font
module을 통해 Inter라는 font를 사용하고 font의 weight를 400과 800으로 지정하여 build한다면 결과로 나오는 @font-face
는 대략 다음과 같다. ( Next가 생성하는 결과와 정확히 일치하지는 않으며 설명을 위한 용도임을 참고하자 )
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/_next/static/../Inter-Regular.ttf) format("woff2");
unicode-range: u+0460-052f, u+1c80-1c88, u+20b4, u+2de0-2dff, u+a640-a69f,
u+fe2e-fe2f;
}
@font-face {
font-family: "Inter";
font-style: normal;
font-weight: 800;
font-display: swap;
src: url(/_next/static/../Inter-ExtraBold.ttf) format("woff2");
unicode-range: u+0301, u+0400-045f, u+0490-0491, u+04b0-04b1, u+2116;
}
font-family: 해당 font-face의 value로 사용될 이름이다. 특정 class에 font-family 이름을 제공할 때 사용하는 이름을 선정한다.
font-style: 해당 font-face에 적용할 style이다. font마다 지원되는 style이 다르며 보통 normal이나 Italic style을 지원한다.
font-weight: 해당 font-face의 weight를 뜻한다. 같은 font 파일이라도 font 굵기에 따라 파일이 다르게 존재한다. 위의 예제에서 font-weight:400에 해당하는
@font-face
에서는 Inter-Regular font 파일을 사용하고 있고 font-weight:800에 해당하는@font-face
에서는 Inter-ExtraBold font 파일을 사용하고 있다. 즉, 다음과 같이 font-family와 font-weight를 선언하고 해당 class를 text element에 사용한다면 해당 text에 Inter-ExtraBold font가 적용되는 것이다..oswald { font-family: "Oswald", sans-serif; font-weight: 800; }
<div className="oswald">Test Font</div> // Inter-ExtraBold font가 적용된다.
특정 class에
font-family:”Inter”, font-weight:800
을 선언하고 해당 class를 text element에 사용한다면 해당 text에 Inter-ExtraBold font가 적용되는 것이다.font-display: font 파일이 load되어 사용 가능한 상태이거나 load에 실패하여 사용 불가능한 상태일 때 어떤 방식으로 font를 display할지 결정한다.
src : 실제 font file이 있는 위치를 지정한다. src에 지정한 font file이 해당 font-face에 사용된다. 그렇기에 font-weight를 800으로 설정해도 src에서 Light version의 font file을 설정하면 실제 font는 Light version의 font가 사용된다.
@font-face { font-family: "Oswald"; font-weight: 800; font-style: normal; src: url("/fonts/Oswald/Oswald-Light.ttf") format("truetype"); } .oswald { font-family: "Oswald", sans-serif; font-weight: 800; }
<div className="oswald">Test Font</div>
위의 예제에서 font-weight를 800으로 설정했지만 실제로 적용되는 font는 Light version의 font다. 대표적으로 font file type에 따라 설정하는 format list는 다음과 같다.
font/ttf : truetype font/otf : opentype font/woff : woff font/woff2 : woff2
만약 여러개의 url이 설정되어 있으면 제일 먼저 선언된 font를 load하려고 시도하고 만약 해당 font를 load할 수 없으면 다음 선언된 font를 load한다.
@font-face { font-family: "Oswald"; font-weight: 800; font-style: normal; src: url("/fonts/Oswald/Oswald-Light.woff2") format("woff2"), url("/fonts/Oswald/Oswald-Light.ttf") format("truetype"); }
unicode-range : font가 적용되는 unicode character의 범위를 설정한다. font가 지원하는 character의 범위를 unicode-range를 통해 설정할 수 있다. 특정 unicode character 하나만 설정할 수도 있고 특정 범위를 모두 포함하는 범위 형식으로 설정할 수도 있다. 예를들어
unicode-range: U+0025-00FF
로 설정하면U+0025
와U+00FF
사이의 모든 문자를 포함한다.U+26
은 & 기호를 나타내기 위한 unicode character다. 만약 unicode-range에U+26
만 설정하면 해당 font는 & 기호에만 적용된다.@font-face { font-family: "Oswald"; font-weight: 800; font-style: normal; src: url("/fonts/Oswald/Oswald-Light.ttf") format("truetype"); unicode-range: U+26; } .oswald { font-family: "Oswald", sans-serif; font-weight: 800; }
<div className="oswald">Test & Font</div>
위의 예제에서 Oswald font는 & 문자에만 적용된다. 만약 unicode-range에 설정한 unicode character가 page에 존재하지 않으면 browser는 font를 load하지 않는다. 즉, unicode-range가
U+26
로 설정되어 있고 접속하는 페이지에 & 기호가 없으면 browser를 font를 load하지 않는다.unicode-range를 반드시 설정할 필요는 없지만
next/font
module을 통해 사용한 font는 build시 NextJS에서 unicode-range를 추가해준다.
지금까지 next/font
module이 font-optimization을 위해 @font-face
를 생성해주고 @font-face
의 property가 어떤 역할을 하는지 살펴보았다. 이제 본격적으로 next/font
module을 살펴보자
next/font
next/font
는 build-in module이기에 별도의 설치 없이 바로 사용할 수 있다. next/font
을 통해 google font가 제공하는 font를 사용할 수 있고 또는 local에 위치한 custom font를 사용할 수도 있다.
우선 google font를 사용하는 예제부터 살펴보자.
import { Oswald } from "next/font/google";
const oswald = Oswald({
subsets: ["latin"],
weight: ["400"],
});
const TestPage = () => {
return (
<div className={oswald.className}>Test Font</div>
)
}
위의 예제는 next/font
모듈을 통해 oswald font를 import해 사용하는 예제이다. Oswald font module을 통해 해당 font의 정보를 가진 객체를 생성하고 해당 객체의 className을 원하는 element의 className에 전달해주면 해당 element에 font가 적용된다.
이렇게 사용된 google font는 project build시 모두 download 되어 build proejct에 포함이 되며 application production에서 운영될 때 font를 load하기 위해 google font server로 추가 요청을 보내지 않는다.
localFont
만약 local에 위치한 custom font를 사용해야 한다면 NextJS가 제공하는 next/font/local
module을 이용한다.
import localFont from "next/font/local";
const localOswald = localFont({
src: "./fonts/Oswald/Oswald-Regular.woff2",
});
const TestPage = () => {
return (
<div className={localOswald.className}>Test Font</div>
)
}
위의 예제처럼 localFont module을 import하고 src property에 사용하고자 하는 font file의 path를 지정해 준다. 그렇게 import한 custom font의 적용법은 기존과 동일하다. font를 적용하고 싶은 element에 className을 전달해준다.
만약 여러개의 font file을 import하고자 한다면 src property를 array로 변경하여 import한다.
const localOswald = localFont({
src: [
{
path: './fonts/Oswald/Oswald-Regular.woff2',
weight: '400',
style: 'normal',
},
{
path: './fonts/Oswald/Oswald-Bold.woff2',
weight: '800',
style: 'normal',
}
],
});