블로그 개발 중, 네트워크 스로틀링(거의 3G ~ Slow 4G)을 걸어놓은 환경에서 테스트를 했던 적이 있었습니다. 그 때 폰트가 매우 느리게 로드되는 것을 알게 되었습니다. 문서의 기본적인 HTML 구조나 스타일은 비교적 빠르게 적용되었지만, 폰트는 엄청 느리게 적용되었습니다.
네트워크 탭을 확인해 보니 대부분의 파일은 많아봤자 50kb, 평균 10~20kb 정도의 크기인 것에 비해 폰트 파일은 1,000~2,000kb 정도의 크기였습니다. 거의 100~200배의 용량 차이가 나는 것이죠.
폰트 파일의 용량이 너무 큰 탓에 폰트 적용이 너무 느렸습니다.
로고에 사용된 FZuanSu 초서체 폰트
특히, 로고에만 사용되는 “FZuanSu”라는 초서체 폰트를 최적화하기로 했습니다.
라이브 프로덕션 환경에서 폰트 파일의 크기는 약 2,150kb이며 총 로드 시간은 약 59ms입니다.
unicode-range로 해결?
먼저 떠오른 개선 방법은 unicode-range였습니다. 옛날에 어느 아티클에서 폰트 최적화 방법 중 하나로 본 적이 있었기 때문입니다. 하지만 그 방식은 직접적인 성능 개선 효과는 없습니다. 정확히는 “폰트를 로드하는 조건을 설정”하는 기능이기 때문입니다.
일반적으로 브라우저는 @font-face 구문을 만나면 해당 폰트 파일을 즉시 로드합니다. 허나 unicode-range 속성이 설정되어 있다면, 브라우저는 지정된 글자가 화면에 나타났을 때 폰트 파일을 로드합니다. 즉 느긋한 로드를 하는거죠. 랜딩 페이지에 지정한 글자가 없다면, 브라우저는 폰트 파일을 로드하지 않습니다. 따라서 렌더링 시 불필요한 리소스를 패치하지 않습니다. 간접적으로 성능 향상 효과를 누릴수 있습니다.
하지만 결국 화면에 특정 글자가 나타나서 폰트 파일을 로드해야 하는 경우, 브라우저는 폰트 파일 전부를 패치합니다. 2,150kb의 파일을 전부 로드하는 것이죠.
그에 비해 제 블로그에서는 "香格裏拉”, 단 네 글자밖에 사용하지 않습니다. 네 글자를 표현하기 위해 저 어마어마한 폰트 파일을 전부 패치하는 것은 비효율적입니다.
폰트 서브세팅
그래서 폰트 서브세팅을 이용해 최적화하기로 결정했습니다. 폰트 서브세팅 도구인 fonttools를 설치한 뒤, 다음 명령어를 통해 단 네 가지 글자만 포함한 폰트 서브셋 파일을 생성했습니다.
/* before */@font-face{font-family:"FZuanSu";src:url("/fonts/FZuanSu/FZuanSu.ttf")format("truetype");font-display: swap;}/* after */@font-face{font-family:"FZuanSu";src:url("/fonts/FZuanSu/FZuanSu-subset.woff2")format("woff2");font-display: swap;unicode-range: U+9999, U+683C, U+91CC, U+62C9;}
만약 서브셋에 포함되지 않는 문자가 걱정된다면 fallback 처리를 할 수 있습니다.
/* 香, 格, 裏, 拉 네 가지 글자만 포함한 서브셋 파일 */@font-face{font-family:"FZuanSu";src:url("/fonts/FZuanSu/FZuanSu-subset.woff2")format("woff2");font-display: swap;unicode-range: U+9999, U+683C, U+91CC, U+62C9;}/* fallback 폰트 파일 */@font-face{font-family:"FZuanSu";src:url("/fonts/FZuanSu/FZuanSu.ttf")format("truetype");font-display: swap;}
약 760배의 성능 향상
최적화 이전 로컬 프로덕션 환경에서 폰트 파일의 크기는 약 2,170kb이며 총 로드 시간은 약 172ms입니다.
최적화 이후 로컬 프로덕션 환경에서 폰트 파일 용량은 2.8kb에 총 로드 시간은 4ms입니다.
최적화 이후 라이브 프로덕션 환경에서 파일 용량은 2.8kb에 총 로드 시간은 15ms입니다.
최적화 이전
최적화 이후
로컬 + 프로덕션
2,170kb / 172ms
2.8kb / 4ms
라이브 + 프로덕션
2,146kb / 59ms
2.8kb / 15ms
라이브 프로덕션 환경 기준으로 용량은 766배 절약했고 총 로드 시간은 43배 빨라졌습니다.
한계
폰트 서브셋은 폰트 파일 자체의 용량을 줄여 성능을 직접적으로 개선할 수 있는 근본적인 방법 중 하나입니다. 하지만 사용될 글자를 미리 예측하기란 어렵습니다. 제 경우엔 로고에만 사용하는 특별한 폰트였기 때문에 드라마틱하게 최적화할 수 있었습니다.
다만 효과가 덜 할지라도, <pre/> 태그에 적용되는 코드용 폰트와 같이 특수한 목적의 폰트는 서브세팅이 좋은 최적화 방법이 될 수 있습니다.
마무리
간단하게 폰트 관련 성능을 획기적으로 개선해보았습니다. 하지만 이 방식을 적용할 수 있는 경우는 많지 않을 것입니다. 그래서 폰트 최적화를 할 수 있는 다양한 방법을 소개해드리면서 글을 마무리하려고 합니다.