페이지를 열면 글자가 한 번 나타났다가 다른 모양으로 바뀌고, 그 순간 제목이 세 줄에서 두 줄로 접히면서 아래 내용이 위로 튀어 오릅니다. 방문자가 막 누르려던 버튼이 자리를 옮기기도 합니다. 웹폰트가 늦게 도착해서 생기는 현상이고, 디자인이 잘못된 것이 아니라 로딩 순서의 문제입니다.
무슨 일이 일어나는가
브라우저는 웹폰트 파일을 내려받는 동안에도 글자를 그려야 합니다. 그래서 우선 시스템에 있는 폴백 글꼴로 그리고, 웹폰트가 도착하면 그것으로 교체합니다. 문제는 두 글꼴의 치수가 다르다는 데 있습니다.
글꼴마다 같은 글자 크기에서도 실제 글자 폭이 다르고, 기준선 위아래로 차지하는 높이가 다릅니다. 폭이 다르면 한 줄에 들어가는 글자 수가 달라지고, 그러면 줄 수가 달라지고, 줄 수가 달라지면 그 아래 모든 요소의 세로 위치가 밀립니다. 이것이 화면이 튀는 정확한 경로입니다.
font-display 는 선택지일 뿐 해결이 아닙니다
가장 먼저 손대게 되는 것이 font-display 인데, 이 속성은 무엇을 포기할지를 고를 뿐 흔들림 자체를 없애지는 못합니다.
대부분의 사이트는 swap 을 씁니다. 글자가 안 보이는 구간이 없어서 가장 안전한 선택이지만, 교체 시점의 흔들림은 그대로 남습니다. 그 흔들림을 없애려면 폴백이 웹폰트와 같은 자리를 차지하게 만들어야 합니다.
메트릭 보정 — 폴백 가족을 웹폰트에 맞춥니다
방법은 시스템 글꼴을 그대로 쓰지 않고, 치수를 조정한 폴백 가족을 하나 선언하는 것입니다. CSS 가 이를 위한 속성을 제공합니다.
@font-face {
font-family: 'Brand Fallback';
src: local('Malgun Gothic'), local('Apple SD Gothic Neo');
/* 아래 네 값은 직접 재서 넣는다 — 웹폰트와 폴백을 같은 크기로
그려 놓고 글자 폭과 기준선 위아래 높이를 비교한 비율이다 */
size-adjust: 100%;
ascent-override: 100%;
descent-override: 22%;
line-gap-override: 0%;
}
body {
font-family: 'Brand Sans', 'Brand Fallback', sans-serif;
}
size-adjust 가 글자 폭을, ascent-override 와 descent-override 가 줄 높이를 맞춥니다. 값은 반드시 직접 측정해서 넣습니다 — 웹폰트와 폴백 후보를 같은 크기로 그려 놓고 폭과 높이를 재서 비율을 구하면 됩니다. 남의 사이트에서 가져온 숫자는 글꼴이 다르면 그대로 틀립니다.
보정이 맞으면 폴백으로 그린 화면과 웹폰트로 그린 화면의 줄바꿈 위치가 같아집니다. 교체는 여전히 일어나지만 글자 모양만 바뀌고 자리는 그대로여서, 화면이 튀지 않습니다.
한글 웹폰트에는 조건이 하나 더 있습니다
한글 글꼴은 글자 수가 많아 파일이 큽니다. 그래서 대개 유니코드 구간별로 잘게 나뉜 서브셋으로 배포되고, 브라우저는 페이지에 실제로 쓰인 글자가 속한 조각만 내려받습니다. 좋은 구조이지만, 조각이 여러 개면 도착 시점도 여러 번이라 흔들림이 여러 번 일어날 수 있습니다.
여기서 첫 화면에 쓰이는 조각만 미리 받아 두는 것이 효과적입니다. 다만 미리 받는 목록이 길어지면 서로 대역폭을 나눠 쓰게 되어 첫 화면 이미지 같은 다른 자원과 경쟁합니다. 그리고 히어로 문구를 고치면 필요한 조각이 달라지므로, 카피를 바꿀 때 이 목록도 함께 확인해야 합니다.
타이포그래피 전반의 설계는 타이포그래피 연재에서 다루고, 첫 화면 로딩 성능에 관한 다른 글은 성능 최적화 아카이브에 있습니다. 폰트 · 이미지 · 캐시를 포함한 전반적인 속도 개선은 최적화 지원 사업에서 함께 처리합니다.