최근에 프로젝트를 react(v18) + next(v13)으로 마이그레이션했다.
next v13 소식중에 가장 간단히 적용해서 좋은 성능 변화를 이끌어낼 수 있을 것 같아보여서 바로 적용해보았다.
@next/font 를 적용하면 세가지 정도 이점이 있어보인다.
제 환경은 next v13.1.1 @next/font v13.1.2 입니다. 추후에 @next/font가 내장되어 있을 확률이 높습니다.
우선, 다운받자.
yarn add @next/font
package.json 에 패키지가 다운받아진 걸 확인했으면 바로 next.config.js 를 열어서 아래 코드를 넣자.
...
experimental: {
fontLoaders: [{ loader: '@next/font/google', options: { subsets: ['latin'] } }],
},
그다음 기존에 구글 폰트를 cdn으로 사용하고 있던 코드를 찾아 없애주자.
필자는 아래와 같이 사용하는 font-family와 font-weight, display 방법을 적용했었다.
<Head>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" />
<link rel="preconnect" href="https://cdn.jsdelivr.net" crossOrigin="true" />
<link
href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100;300;400;500;700;900&display=swap&family=Montserrat:wght@500;700&family=Poppins:wght@600;700&display=swap"
rel="stylesheet" />
...
네트워크를 통해 요청하고 있는 코드를 삭제해주자.
공식 문서에 기재되어있는 일반적인 방법이다.
custom app 폴더에 들어가서 pageProps를 넘기고있는 코드를 감싸는 엘리먼트를 하나 만들고 적용 시키고 싶은 폰트의 className을 className props에 넘겨주면 적용된다.
export const cls = (...classnames: string[]) => {
return classnames.join(' ');
}
<main className={cls(notoSansKr.className, poppins.variable, montserrat.variable)}>
<Component {...pageProps} />
</main>
내가 적용해야 할 구글 폰트는 Noto-Sans-KR, poppins, montserrat 총 3개이다.
const notoSansKr = Noto_Sans_KR({
weight: ['100', '300', '400', '500', '700', '900'],
display: 'swap',
fallback: [
// 디자이너분과 상의한 폴백 폰트 넣으시면 됩니다
'-apple-system',
'Malgun Gothic',
'Apple SD Gothic Neo',
'Roboto',
'Apple Color Emoji',
'Segoe UI Emoji',
'Segoe UI Symbol',
'sans-serif',
],
});
const montserrat = Montserrat({
weight: ['500', '700'],
display: 'swap',
variable: '--montserrat',
});
const poppins = Poppins({
weight: ['600', '700'],
display: 'swap',
variable: '--poppins',
});
css-variables 방법을 통해 poppins와 monserrat를 적용시키고 전체폰트로 적용시켜야 할 Noto-Sans-KR 모듈을 찾아 import 하고 className 메서드를 통해 자체 호스팅 된 폰트를 적용시켰다.
이렇게 나오면 잘 적용된거다.
// as-is
font-family : Poppins;
font-family : 'Montserrat';
// to-be
font-family : var(--poppins);
font-family : var(--montserrat);
위와 같이 폰트 적용한 코드를 삭제하고 css variables 방법으로 사용하면 된다.
그리고 전역적으로 적용해놓았던 Noto-Sans-KR도 삭제하면 된다.
엘리먼트로 한번 감싸서 className으로 넘기는 방법 말고 global css로 적용시키는 방법도 있다.
// globalStyles.ts
...
* {
font-family: ${notoSansKr.style.fontFamily};
...
}
이렇게 하면 user agent stylesheet도 덮어쓸 수 있어서 좋다.
@next/font 적용 결과, 폰트 관련 네트워크 페이로드가 3646kb => 0kb로 완전히 사라졌다.
fonts.gstatic.com과 같은 타사 리소스를 사용하는 대신 글꼴을 로컬에서 호스팅하여 렌더링 프로세스 속도를 높일 수 있었다.
그리고 CLS 점수에 악영향을 미치는 일반적인 문제인 FOIT(보이지 않는 텍스트 깜박임)를 방지할 수도 있었다.