폰트 최적화, 그리고 next/font

2cham_ny·2024년 3월 15일
0

TIL

목록 보기
8/8

01 - WHAT

매번 프로젝트를 시작할 때 어떻게 하면 폰트 설정을 ‘잘’ 할 수 있는지에 대해 고민한 적이 종종 있었다. 하지만 여유가 없어 매번 해왔던 방식으로 로컬에 다운을 받아 사용하거나 혹은 웹폰트를 사용해 진행을 해왔었다.

그 결과, 브라우저가 초기에 띄워질 때 잠깐 동안 폰트가 적용되지 않는 현상이 일어나곤 했다. 이 현상을 FOUT이라고 하는데, 이와 관련해서 더 자세하게 알아보자.

📌 FOUT와 FOIT

  • FOUT(Flash of Unstyled Text)
    • 브라우저가 폰트를 다운로드하기 전까지 폰트가 적용되지 않는 현상
  • FOIT(Flash of Invisible Text)
    • 브라우저가 폰트를 다운로드하기 전까지 텍스트가 보이지 않는 현상
    • 이 방식은 특히 더 지양해야 한다고 한다.

아래 내용은 참고하면 좋을 것 같아 가져와보았다.

CSS font-display 설정
auto : 브라우저의 기본 동작
block : FOIT
swap : FOUT
fallback : 100ms동안 텍스트가 보이지 않고 그 후 렌더링
optional : 네트워크 상태에 맞게 웹폰트 전환 여부 판단

이로써 내가 겪었던 현상은 FOUT이라고 정의할 수 있다. 폰트가 로드되는 속도가 느리기 때문에 페이지 로드 속도 또한 느려지게 되는 현상이 발생한 것이었다.

❓이러한 현상이 왜 일어나는 걸까?

이런 현상을 이해하기 위해선 브라우저의 동작 원리부터 잘 알고 있어야 한다.

[CSS/JS] 웹 폰트를 최적화하는 5가지 방법

위 아티클에 폰트와 관련된 브라우저 동작 원리가 잘 나와있다.

요약을 해보자면,

⇒ CSSOM을 DOM트리와 결합시켜 렌더링 트리를 구성하는 시점에 폰트 리소스를 요청하게 된다.

⇒ 폰트 리소스 요청은 다른 리소스 요청보다 늦게 진행되기 때문에 리소스 응답이 늦어지게 되어 FOUT, FIOT과 같은 현상이 발생하게 된다.

❓이러한 현상을 어떻게 해결할 수 있을까

찾아보니 여러 가지 방법이 있는 것 같다.

1) 웹폰트 리소스 preload

위에서 이야기한 내용과 직결되는 대안일 수 있겠다. 폰트 리소스 요청이 타 리소스보다 늦게 시작되기 때문에 시점을 앞당기는 방안이다. 즉, preload를 사용해 초기에 요청하는 것이다.

<link rel="preload" href="...woff2" as="font" type="font/woff2" ... />

다음과 같이 <head>에서 폰트를 요청할 때 rel=”preload”를 추가하면 된다고 한다. 폰트파일을 미리 다운로드하고 나중에 사이트에 재방문 시 폰트를 새로 렌더링하지 않아도 되기 때문에 최적화가 가능해보인다.

흠..

하지만 단점이 있다! 페이지에 필요한 폰트를 preload해야 하는데, 사용하지 않는 폰트를 preload에 적용하게 되면 로딩 시간이 길어진다고 한다.

결국 최종적으로 문제점을 해소해줄 수 있는 방안은 아닌 듯하다.

2) 용량이 작은 웹폰트 확장자 사용하기

아마 폰트에 대해 찾아본 이들은 한번쯤은 들어봤을 확장자들이 있다.

  • TTF
  • OTF
  • WOFF
  • WOFF2
  • SVG
  • EOT

여러 브라우저에서 지원되고 있는 폰트 포맷이다. 여기서 용량이 큰 순서부터 나열하면 TTF > EOT > WOFF > WOFF2 순이다. WOFF2가 압축률이 가장 좋다고 한다.

3) 서브셋 폰트 사용하기

서브셋 폰트는 폰트에서 불필요한 글자를 제거한 폰트 파일을 뜻한다. 실제 서비스에서 사용하지 않는 조합들을 제거해서 만든 것이 서브셋 폰트이기 때문에, 폰트의 용량을 줄여 최적화가 가능하다.

4) [next 한정] next/font 사용하기

next.js에서 개발을 진행 중인 나는 next/font를 사용함으로써 최적화를 진행하려고 한다.

Optimizing: Fonts

요게 넥스트 공식 문서에 나와 있는 폰트 최적화 방법이다.

본격적으로 공식 문서를 뜯어보자!


📌 Font Optimization in NEXT.js

공식 문서를 잘 살펴보면 다음과 같이 정리할 수 있다.

  • next/font
    • 모든 글꼴 파일에 대해 자동 자체 호스팅이 내장되어 있다. ⇒ 기본 CSS 속성 덕분에 레이아웃 변경 없이 웹 폰트를 최적으로 로드할 수 있다.
    • 개인 정보 보호 및 성능 향상을 위해 외부 네트워크 요청을 제거한다.
    • next/font/local을 import함으로써 사용 가능 ⇒ 넥스트 피셜 가장 좋은 성능과 유연성을 위해 변수 폰트 사용을 권장!

코드와 함께 살펴보자.

공식 문서에 나와있는 코드를 그대로 작성하는 건 큰 의미가 없어보여 현재 진행 중인 프로젝트 코드를 가져와 next/font를 활용해 수정해보겠다.

우리 프로젝트에서는 variable fonts에 없는 pretendard를 사용하고 있기 때문에 따로 정의가 필요하다.

// src > util > fonts.ts

import localFont from "next/font/local";

const pretendard = localFont({
  src: [
    {
      path: "../../public/fonts/Pretendard-SemiBold.woff",
      weight: "700",
    },
    {
      path: "../../public/fonts/Pretendard-Medium.woff",
      weight: "500",
    },
  ],
  variable: "--font-pretendard",
});

export default pretendard;

다음과 같이 localFont를 사용하여 pretendard라는 폰트를 선언할 수 있다. src 안에서 사용하고자 하는 font-weight들을 woff파일로 지정하면 된다.

그리고 우리 프로젝트에선 현재 tailwind를 사용하고 있기에 tailwind.config.ts에서의 수정이 필요하다.

// tailwind.config.ts

...
		  fontFamily: {
        pretendard: ["var(--font-pretendard)"],
      },
...

다음과 같이 속성을 넣어주게 되면, font-pretendard 사용이 가능해진다.

마지막으로 레이아웃에서 적용해준다.

// src > app > layout.tsx

export default function RootLayout({
	children,
}: Readonly<{
	children: React.ReactNode;
}>) {
	return (
		<html lang="en" className={`${pretendard.variable} font-pretendard`}>
		...
		</html>
	);
}
  • ${pretendard.variable}
    • 실제로 사용자의 브라우저에서 로드되는 폰트 경로를 나타낸다.

    • localFont 함수를 사용해 정의된 변수이기 때문에 폰트 파일의 경로를 나타내는 것이다.

      ⇒ 웹 페이지가 로드될 때 브라우저가 해당 경로에서 폰트를 가져오게 된다.

      ⇒ 폰트를 동적으로 로드하기 위한 변수라고도 할 수 있다.

  • font-pretendard
    • 폰트가 로드되지 않았을 때의 대체 폰트를 지정한 부분이다.
    • 폰트가 로드되지 않았을 때 시스템 기본 폰트 또는 다른 대체 폰트를 사용하려면 이러한 폴백 폰트를 지정해야 한다.

요기서 잠깐..!

❓왜 폴백 폰트가 필요한 걸까?

우선 폴백 폰트의 정의는 다음과 같다.

  • 폴백 폰트(fallback font) : 웹페이지가 특정 폰트를 로드하지 못했을 때, 대체로 사용되는 폰트

즉, 폴백 폰트는 웹페이지가 예상대로 showing할 수 있도록 하는 데에 도움이 된다고 말할 수 있다.

웹 개발을 해본 사람이라면, 아래 사진과 같이 보통 폰트 목록을 지정할 때, 여러 폰트가 차례로 나열되어 있는 걸 많이 봤을 것이다. 브라우저는 목록에서 첫 번째로 지정된 폰트부터 차례로 시도하게 된다. 만약 해당 폰트를 사용할 수 없는 경우 다음 폰트로 넘어가게 된다.

이러한 방식으로 웹 페이지가 다양한 환경에서 적절하게 렌더링될 수 있도록 보장할 수 있는 것이다.

항상 개발하면서 왜 이렇게 많이 쓰나 궁금했었는데.. 해결되었다!! 와~

정리하자면!

폴백 폰트는 웹 페이지의 일관된 모양과 느낌을 유지하고 UX를 개선하는 데에 중요한 역할을 한다.

02 - HOW

  • 문제 상황 : 프로젝트 진행 중 폰트 적용이 효율적으로 이루어지지 않았다.
  • 개선 방법 : 폰트 최적화 방법을 알아본 후 next에서 제공하는 next/font를 활용해 UX를 개선할 수 있었다.

[참고한 글]

웹 폰트 사용과 최적화의 최근 동향

폰트가 어떻게 동작하는지에 대해 잘 나와있는 것 같다!

03 - RETROSPECT

이전까진 폰트 관련해서 제대로 정리해본 적이 없었기에 이번 포스팅은 유독 많은 인사이트를 얻을 수 있었던 것 같다. 그리고 이렇게 폰트 최적화 방법이 다양한 줄 몰랐었다.

역시 난 우물 안 개구리! ^,^ 더 많이 공부해야겠다~

04 - 오늘의 한마디

폰트 및 환경 세팅부터 다시 리팩토링을 시작하고 있는데 너무 즐겁다!

앞으로도 계속 이렇게 즐겁게 작업할 수 있었으면 좋겠당 😈

profile
😈 기록하며 성장하자!

0개의 댓글