로컬 폰트와 웹 폰트의 개념을 정리해보자.
브라우저는 HTML 문서를 요청하고, 응답받은 HTML를 기반으로 DOM 트리를 구성한다.
CSS, JS 등 리소스를 요청하고 응답받은 CSS를 기반으로 CSSOM 트리를 구성한다. 만약 웹폰트를 정의한 경우, 폰트 리소스를 요청한다.
폰트 리소스를 응답받을 때까지 브라우저는 layout 계산을 수행한다.
그리고 paint 단계에서 폰트 리소스의 다운로드가 완료되지않았다면 해당 폰트를 사용하는 부분의 렌더링을 차단한다.
브라우저의 렌더링 차단 방식은 2가지가 존재한다.
IE 계열 브라우저는 FOUT 방식을 사용한다. 웹폰트가 준비될 때까지 폴백 폰트를 사용하여 렌더링한다. 그리고 웹폰트가 다운로드되면 변경한다.
Chrome, Firefox 등 브라우저는 FOIT 방식을 사용한다. 최대 3초동안 텍스트를 숨기고 3초가 지나면 폴백 폰트를 렌더링한다. 웹폰트가 다운로드되면 변경한다.
Safari는 웹폰트가 다운로드될 때까지 텍스트를 숨긴다.
그러나 FOIT 방식은 사용자가 텍스트를 볼 수 없기 때문에 UX 측면에서 권장되지 않는다. 개발자는 font-display 속성을 사용하여 브라우저의 폰트 렌더링 차단 방식을 제어할 수 있다.
@font-face {
font-display: auto | block | swap | fallback | optional;
}
font-display에는 5가지 속성이 존재한다. 각 속성은 차단 기간과 교체 기간이 다르다. 차단 기간이란, 웹폰트가 준비되지않아 텍스트 렌더링을 차단하는 기간을 말한다. 그리고 교체 기간은 웹폰트가 준비되었을 때 교체(swap)하는 기간을 말한다.
분류 | 차단 기간 | 교체 기간 |
---|---|---|
auto | 브라우저 기본동작 | 브라우저 기본동작 |
block | 3초 | 무한 |
swap | 0ms | 무한 |
fallback | 0.1초 | 3초 |
optional | 0.1초 | 없음 |
block은 웹폰트가 로드되지않으면 3초동안 텍스트를 렌더링을 차단하다. 3초 내에 로드되지 않으면 폴백 폰트를 적용하고 웹폰트가 준비되면 웹폰트로 교체한다.
swap은 웹폰트가 로드될 때까지 폴백 폰트를 적용하고, 웹폰트가 준비되면 교체한다.
fallback은 0.1초 렌더링을 차단하고 폴백 폰트를 적용한다. 3초 안에 웹폰트가 로드되면 웹폰트로 교체한다. 그러나 3초 안에 웹폰트가 로드되지 않으면 웹폰트를 캐시에 저장하고 교체하지 않는다. 그래서 사용자가 페이지를 재방문하게 되면 웹폰트를 바로 적용한다. 웹폰트 적용보다 사용자가 빨리 읽는게 중요한 '본문 텍스트' 같은 경우 해당 방식이 권장된다.
optional은 0.1초동안 렌더링을 차단한다. 만약 웹폰트가 first-paint 단계에서 즉시 사용할 수 있는 경우(only-if-cached) 웹폰트를 적용한다. 그렇지 않은 경우, 브라우저가 후순위로 폰트 다운로드를 요청하거나 요청을 중단할 수 있다.
https://static-misc.glitch.me/optional-font-load/ 에서 font-display: optional 방식을 체험해볼 수 있다.
TTF(TrueType Font)는 Apple과 MS에서 개발하였으며 가장 오랫동안 사용된 폰트 포맷이다.
OTF(OpenType Font)는 Adobe와 MS에서 TrueType을 기반으로 개발한 폰트 포맷이다. TTF와 차이점은 타이포그래피 관련해서 더 유연한 확장성을 갖고 있다.
WOFF(Web Open Font Format)는 웹에 최적화된 폰트 포맷으로, TTF와 OTF를 웹에서 사용 가능한 형식으로 변환하여 압축되어있다.
WOFF2는 WOFF보다 약 30% 가량 압축률이 높아 로딩 속도가 빠른 파일 포맷이다.
https://www.w3schools.com/Css/css3_fonts.asp
브라우저 별로 폰트 포맷 지원 범위가 다르지만, 서비스의 브라우저 대응 스펙을 고려해 WOFF2 혹은 WOFF 포맷을 사용하여 용량을 줄일 수 있다.
unicode-range란 폰트를 적용할 문자 범위를 설정하는 속성으로 페이지에서 필요한 폰트 리소스만 다운로드하여 네트워크 대역폭을 절약할 수 있다.
예를 들어 '컴포넌트'라는 텍스트를 가진 버튼이 있다면, 한글 유니코드표를 참조하여 '컴(U+D3EC)'과 '포(U+CEF4)'라는 글자에만 폰트를 적용할 수 있다.
@font-face {
font-family: 'NeoDunggeunmoPro';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2302@1.0/NeoDunggeunmoPro-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'NeoDunggeunmoPro';
src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2302@1.0/NeoDunggeunmoPro-Regular.woff2') format('woff2');
font-weight: normal;
font-style: normal;
unicode-range: U+D3EC, U+CEF4;
}
브라우저는 페이지에 unicode-range에 해당하는 글자가 있다면 전체 글꼴을 다운받고, 그렇지 않으면 폰트를 다운로드 받지 않는다.
출처
https://d2.naver.com/helloworld/4969726
https://wit.nts-corp.com/2017/02/13/4258
https://iainbean.com/posts/2021/5-steps-to-faster-web-fonts/
https://drafts.csswg.org/css-fonts-4/#font-display-desc
유용한 내용 감사합니다.