16. 웹 폰트 최적화
16. 웹 폰트 최적화

16. 웹 폰트 최적화

Authors
Date
Tags
Published
Published
Slug
 
 
날이 갈수록 발전해가는 웹 애플리케이션에서 이제는 대부분 기본적인 폰트가 아닌 다양한 폰트를 사용하고 있다.
브라우저에서 새로운 폰트를 적용하기 위해서는 서버에서 폰트 리소스를 받아와야하며 이 과정 또한 엔지니어링이 필요할 것이다.
본론으로 들어가기 앞서서, 브라우저가 폰트를 로드하는 과정을 알아보자.
 
 
 
 
 

브라우저가 웹 폰트를 로드하는 과정

notion image
T0 : 브라우저가 HTML 문서를 요청
T1 : DOM을 빌드 및 CSS, JS 및 기타 리소스를 요청
T2 : CSSOM빌드, 폰트 리소스 요청
T3 : 콘텐츠를 그린다. 글자도 이 시점에 그려진다.
 
위에서 볼 수 있듯이 폰트 리소스는 가장 나중에 요청을 시작하고, 응답 또한 다른 리소스에 비해 늦다.
하지만 폰트가 늦게 적용될수록 FCP(First Contentful Paint), LCP(Largest Contentful Paint) 등 성능 지표에도 영향이 있기 때문에 폰트를 빠르게 적용시키기 위한 최적화 엔지니어링이 필요할 것이다.
 
 
 
 
 

폰트 압축

우선 더 용량이 작은 폰트 파일을 사용하는 방법이 있다.
폰트 파일에는 다양한 종류가 있는데 각 특징은 아래와 같다.
notion image
 
 
 
일반적으로 많이 사용하는 TTF, OTF 폰트의 경우에는 웹에서 사용하기에는 용량이 다소 크다.
압축률이 가장 좋은 WOFF2 폰트를 사용하여 용량을 줄일 수 있다.
notion image
notion image
(Pretendard기준 약 3배 이상 차이나는 모습)
 
 
 
 
 

폰트 로드 전략

폰트 로드 전략을 잘 사용하면 사용자가 글자를 더 빨리 볼 수 있을 뿐만 아니라 위화감 없이 자연스러운 사용자 경험을 만들어 낼 수 있다.
notion image
T2와 T3 사이의 시점에서 콘텐츠가 브라우저에 그려지는 시점에서는 폰트 로드 전략에 따라 글자가 보일 수도 있고, 안 보일 수도 있다.
 
폰트 로드 전략은 크게 두가지로 나뉜다.
notion image
FOIT: 폰트가 로드되지 않으면 글자를 보여주지 않는다.
FOUT: 폰트가 로드되지 않으면 설정된 fallback font를 적용한다.
 
FOIT방식을 사용할경우 글자가 보이지 않아 사용자에게 전혀 다른 의미의 내용을 전달할 수도 있다.
FOUT방식을 사용하는것이 일반적으로 더 이점이 많다.
 
 
 
notion image
FOUT방식을 사용하기 위해 fallback font를 설정하려면 이런식으로 font-family 속성에 왼쪽부터 최종적으로 적용할 폰트를 넣으면 된다.
여기서는 마지막에 sans-serif 를 추가하였는데 마지막 fallback font로는 시스템이 기본적으로 가지고 있는 폰트(web safe font, system font)를 넣어주어야 한다.
정확히는 sans-serif는 폰트가 아닌 폰트 페밀리이다. sans-serif 안에도 여러 폰트가 있으며, 운영체제나 애플리케이션 환경에 따라 설정된 폰트가 적용된다.
 
 
많이 사용되는 폰트 패밀리는 아래와 같이 5개이고 각 폰트 페밀리는 다른 특징을 기준으로 구분된다.
notion image
 
 
 
 
 

FOUT 적용하는법

notion image
FOUT 방식을 사용하기 위해서는 위와 같이 @font-face의 font-display 속성을 swap 으로 설정하면 된다.
swap 이외에도 다양한 옵션이 있는데, 더 알고싶다면 아래의 MDN을 참고하기 바란다.
 
 
 
 
 

서브셋 폰트

서브셋 폰트란 폰트 파일에서 불필요한 글자들을 제거하고 사용할 글자만 남겨둔 폰트를 말한다.
notion image
예시로 과 같이 잘 안쓰이는 글자는 제거하여 폰트 파일을 더 줄일 수 있다.
폰트 제작 툴을 이용하여 폰트 파일을 커스텀 할 수 있지만, 이렇게 까지는 잘 하지 않는다.
 
 
notion image
일반적으로 @font-face의 unicode-range 속성으로 사용할 유니코드 범위만 지정하여 최적화 할 수 있다.
notion image
 
 
 
 
 

Preload

마지막으로, 폰트 파일을 preload 하여 더 빠르게 요청하는 방법이다.
<link rel="preload" href="./nanumGothic.woff2" as="font" type=" font/woff2" crossorigin="anonymous" />
이처럼 link태그의 rel 옵션을 ‘preload’로 설정하면 css를 요청하는 시점에 폰트도 같이 요청할 수 있다.
하지만 요청하는 리소스가 많아 초기 로드가 느려질 수도 있으니 주의가 필요하다.
 
 
notion image
 
만약 구글 폰트와 같은 외부 cdn에서 폰트 파일을 요청하는 경우라면 ‘preload’가 아닌 ‘preconnect’로 설정하는 것이 좋다.
폰트를 내려받기 위해서는 tcp handshaking 과정이 필요한데, 현재 호스팅 서버가 아닌 외부 cdn에 별도로 tcp handshaking이 이루어지기에 더 늦어지는것을 ‘preconnect’로 최적화 할 수 있기 때문이다.
 
preconnect 사용 전:
notion image
 
preconnect 사용 후:
notion image
 
 
 
 
 
 

≤ Next.13

Next.js 13 버전 이상에서는 next/font를 통해 더 간단한 코드로 폰트 최적화를 도와준다.
 
 

self hosting

Next.js 에서는 폰트 파일을 함께 호스팅 하기 때문에 외부 cdn에서 폰트를 가져오거나 따로 폰트를 배포할 수고를 덜어준다.
 

zero layout shift

FOUT방식을 사용하게 되면 폰트가 바뀌면서 폰트의 크기 차이로 인해 레이아웃이 조금씩 바뀌게 된다.
이는 폰트 최적화에서 가장 까다로운 부분이라고 할 수 있다.
notion image
notion image
 
 
하지만 Next.js 13 이상에서는 각 폰트의 크기를 비교하여 css 속성 중 size-adjust 속성을 조절하여 폰트간의 크기를 동일하게 맞춘다.
뿐 만 아니라 세밀하게 조정하기 위해 ascent-override, descent-override, line-gap-override 속성도 조정하여 폰트가 바뀌어도 레이아웃의 변형이 전혀 없도록 구현된다.
 
notion image
notion image
실제로 Next.js의 코드를 뜯어보면, 각 폰트의 크기에 대한 세부 속성이 하드코딩 되어있는 모습을 확인할 수 있다..
 
 
 
 
 
 

Refs