웹 폰트와 웹 폰트 최적화

apro_xo·2022년 12월 8일
3
post-thumbnail

웹 폰트란?

방문자의 로컬 컴퓨터의 폰트 설치 여부와 상관없이 온라인의 특정 서버에 위치한 폰트 파일을 다운로드하여 화면에 표시해주는 웹 전용 폰트이다.

웹 폰트의 장/단점

웹 폰트는 위에서 언급했듯이 방문자의 로컬 컴퓨터의 폰트 설치 여부와 상관없이 화면에 폰트를 보여줄 수 있다는 것이다.

그렇다면 단점은 뭘까❓

웹 폰트는 용량이 매우 무거우며 웹에서 폰트를 불러와서 사용하는 것이기 때문에 웹의 성능 저하를 불러온다. 또한 사용자의 네트워크 환경에 따라 시스템 폰트에서 웹 폰트로 변화는 과정이 사용자에게 보이는 현상이 발생할 수 있다. 이 경우, 좋은 사용자 경험을 제공할 수 없다.

따라서 우리는 웹 폰트 최적화를 통해 위의 속도 문제로 발생하는 단점들을 해결해야한다.

웹 폰트로 인한 문제 사례

웹 폰트 최적화에 대해 검색하고 공부하면서 찾아본 레퍼런스에서 거의 대부분 다루던 사례이다.

아래는 2016년에 미국의 상원 의원인 Mitt Romney에 관한 기사인데, 웹 폰트가 로딩되기 전과 후의 화면을 비교한 그림이다.

Not을 강조하기 위해 Not에만 웹 폰트를 적용하였는데, 로딩이 늦어 정반대의 뜻이 되어버린 것이다.
Not이 없이 기사가 노출된 시간은 불과 몇 초이지만, 전혀 다른 내용이 사용자들에게 전달 되었다.
이 사건으로 인해 미국에서 웹 폰트가 이슈가 되었다고 한다.

사례의 문제 원인

위 사례의 원인을 파악하기 위해서는 브라우저의 렌더링 과정을 살펴보아야한다.
브라우저 렌더링 과정에 대해 전체적으로 다루지는 않을 것이다.

저번에 브라우저의 렌더링 과정에 대해 포스팅 했었는데 참고❗
https://velog.io/@apro_xo/WIL-7.17.7-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0

📌 브라우저 파싱 단계에서 CSSOM을 생성할 때 웹 폰트 로딩을 시작한다.
📌 페인트 단계에서 웹 폰트 파일처럼 외부 링크로 연결된 파일의 다운로드가 완료되지 않았다면 해당 리소스를 사용하는 콘텐츠의 렌더링을 차단한다.

따라서 사용자의 네트워크 환경 및 속도, 웹 폰트의 용량, 웹 폰트가 적용된 텍스트가 보이지 않는 현상 때문에 발생한 문제라고 정의할 수 있다.

사용자의 네트워크는 제어가 불가능하므로 웹 폰트의 용량과 웹 폰트가 적용된 텍스트가 보이지 않는 현상을 최적화를 통해 완화하여 문제를 해결해보자.

웹 폰트 최적화 방법

1. 폰트 파일의 용량 줄이기

웹 폰트는 네트워크를 통해 웹에서 다운로드하는 리소스이기 때문에 폰트 파일의 크기가 클수록 다운로드 및 적용이 오래 걸린다. 따라서 폰트 파일의 용량을 최적화하여 완화할 수 있다.

1-1. 모던한 폰트 형식 사용

폰트의 형식은 매우 다양하다. 폰트의 형식마다 용량이 다르고, 브라우저가 지원하는 형식도 다 다르다는 것이 중요하다.

주로 4가지의 형식이 쓰이는데, 아래와 같다.

👉 EOT: IE8 이하일 경우
👉 TTF: 구형 안드로이드 버전(4.4)에서 필요.
👉 WOFF: 대부분의 모던 브라우저에서 지원
👉 WOFF2: WOFF보다 압축률이 30% 정도 더 좋음

아래는 브라우저별 폰트 지원 현황이다.

WOFF2의 경우, IE에서 아예 지원하지 않았는데, IE가 없어져서 편-안..👍

WOFF2는 압축률이 가장 좋아 용량이 제일 작다. 따라서 WOFF2를 사용하는 것이 가장 좋지만, 브라우저 버전에 따라 지원하지 않을 수도 있기 때문에 Fallback font를 적용하는 것이 바람직하다.

📌 Fallback font 적용방법

@font-face {
  font-family: 'NanumGothic';
  src: url(/fonts/NanumGothic-Regular.woff2) format("woff2"), 
       url(/fonts/NanumGothic-Regular.woff) format("woff"),
       url(/fonts/NanumGothic-Regular.ttf) format("truetype");
}

사용자의 브라우저가 WOFF2 형식을 지원한다면 WOFF2를 사용하고, 지원하지 않는다면 WOFF를 사용, 또 지원하지 않는다면 TTF 형식을 사용한다. 이를 Fallback font라고 한다.

format()을 통해 파일 형식을 꼭 명시해주어야한다.

1-2. 서브셋 폰트

폰트 파일에서 불필요한 글자를 제거하고 사용할 글자만 남겨둔 폰트

영어는 26개 알파벳으로 이루어져 있다. 영문 폰트는 대소문자 포함 총 72자가 필요하다.
하지만 한글은 자음, 모음의 조합으로 만들 수 있는 글자가 11,172자이다.
따라서 한글 폰트 파일은 영어 폰트 파일보다 용량이 크다.

위 그림은 네이버 기술 블로그에서 가져온 그림인데, 11,172 글자를 사용하는 나눔바른고딕 폰트의 일부분이다.

노란색으로 표시된 글자들은 실생활에서 잘 사용하지 않는다.
이런 불필요한 글자를 제거한 것이 서브셋 폰트이다. 따라서 서브셋 폰트는 용량이 작다.

실제로 나눔바른고딕 폰트의 서브셋 폰트는 2,350자로, 기존 용량 2.4MB에서 586KB로 줄어들었다고 한다.

최근에 출시되는 한글 웹 폰트의 대부분이 2,350자의 서브셋 폰트이긴 하나 만약 아니라면 서브셋 폰트를 만들어서 사용할 수 있다.
서브셋 폰트는 サブセットフォントメーカー(이하 서브셋 폰트 메이커)fontTools 라이브러리를 사용해 만들 수 있다.

2. 불필요한 다운로드 막기

2-1. unicode-range

@font-face {
  font-family: NanumFont;
  src: url(NanumPenWeb.woff2) format('woff2');
  unicode-range: U+BC14, U+CC28;
}

U+BC14는 '바', U+CC28는 '차'에 해당하는 유니코드다. 따라서 전체 텍스트에서 '바', '차'에만 폰트가 적용이 된다.

unicode-range 속성을 사용하면 필요한 텍스트에만 폰트를 적용할 수 있고, 텍스트가 없으면 웹에 다운로드를 요청하지 않는다. 불필요한 다운로드를 막을 수 있다.

2-2. local

CSS에 폰트를 선언하면 시스템에 폰트 유무와 관계없이 무조건 폰트를 다운로드하게 된다.

local을 사용하면 시스템에 폰트가 설치되어 있다면 불필요하게 다운로드를 하지 않는다.

src: local('Nanum-Gothic'), 
     url(/fonts/NanumGothic-Regular.woff2) format("woff2"), 
     url(/fonts/NanumGothic-Regular.woff) format("woff");

3. 텍스트가 항상 보이게 하기

3-1. 브라우저의 렌더링 차단 처리 방식(FOIT vs FOUT)

우선 IE 계열 브라우저는 FOUT(Flash Of Unstyled Text) 방식으로 렌더링 차단을 처리하고, 그 외의 브라우저는 FOIT(Flash Of Invisible Text) 방식으로 렌더링 차단을 처리한다.

웹 폰트가 적용될 때는 텍스트의 번쩍임(flash of text)이 일어난다.

웹 폰트가 적용되지 않은 폴백 폰트 상태에서 폰트가 바뀌면서 텍스트 번쩍임이 일어나는 것이 FOUT이고, 웹 폰트가 적용되지 않은 텍스트가 보이지 않는 상태에서 폰트가 바뀌면서 텍스트 번쩍임이 일어나는 것이 FOIT이다.

앞서 다뤘던 사례에서는 FOIT 방식으로 인해 웹 폰트가 적용되기 전의 텍스트가 렌더링 되지 않았던 것이다.

📌 FOUT 방식의 문제점은 없을까?

FOUT 방식은 fallback font나 system font를 먼저 보여주고, web font가 다운로드가 완료되면 웹 폰트를 적용시켜 보여준다.
이 과정에서 system font와 web font는 자간, 높이 등이 다르기 때문에 레이아웃이 깨질 가능성이 높다.

따라서 웹 폰트가 다운로드가 완료되고 적용되면 브라우저는 reflow를 통해 레이아웃을 다시 계산해야한다.

또한 좋은 사용자 경험을 제공할 수 없다.

따라서 font-size-adjust 속성이나 letter-spacing, line-height 등을 조정하여 최대한 적게 변하도록 수정해야한다.

3-2. FOUT 방식을 사용한 최적화

IE 계열의 브라우저를 제외하고 Chorme이나 safari 같은 경우에는 FOIT 방식을 채택하고 있기 때문에 웹 폰트가 적용되지 않으면 텍스트가 보이지 않는다.
따라서 FOUT 방식으로 동작하여 텍스트가 노출되도록 최적화를 진행하는 방법이다.

📌 preload 옵션으로 먼저 로딩

<link>태그의 rel 속성에 preload 옵션을 사용하면 해당 리소스를 다른 리소스보다 빨리 로딩한다.
주로 폰트파일, 이미지 파일, 스크립트 파일, 비디오 파일 등 페이지에서 중요도가 높은 자원을 의도적으로 먼저 로딩할 때 사용하는 옵션이다.

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

웹 폰트 파일에 preload를 사용하면 CSS파일보다 먼저 웹 폰트 파일 다운로드를 시작한다.

preload가 적용되는 브라우저들을 잘 확인하고 사용해야 한다.

📌 font-display

@font-face에 font-display 속성을 추가한다.

속성 값에는 auto, block, swap, fallback, optional의 5가지 옵션이 있다.

👉 block
block은 FOIT와 동일하게 작동하는 옵션이다. 웹 폰트가 로딩되지 않았을 때는 텍스트를 렌더링하지 않는다. 로딩이 완료되면 적용한다.

👉 swap
swap은 FOUT과 동일하게 작동하는 옵션이다. 우선 fallback, system font로 텍스트를 렌더링하고 폰트 로딩이 완료되면 적용한다. 항상 텍스트가 보이게 된다.

👉 fallback
fallback은 우선 100ms 동안 텍스트가 보이지 않고, 그 후 fallback font로 렌더링한다.
약 2초의 전환 시간이 있는데, 이 시간 안에 로딩이 완료되면 웹 폰트로 전환한다.
하지만 이 시간이 지나면 웹 폰트 다운로드가 완료되어도 웹 폰트로 전환하지 않고 fallback font를 유지한다.

👉 optional
optional은 우선 100ms동안 텍스트가 보이지 않고, 그 후 fallback font로 전환한다.
웹 폰트를 다운로드 하지만, 브라우저가 네트워크 상태를 파악해 웹 폰트 전환 여부를 결정한다.

예를 들어 네트워크 연결 상태가 안 좋으면 웹 폰트가 다운로드가 완료되어도 캐시에 저장만 하고 전환은 하지 않는다.

lighthouse

웹 폰트 최적화를 하지 않은 프로젝트를 lighthouse로 성능 측정을 해보았다.

위와 같은 문구를 볼 수 있다.
웹 폰트가 로드 되는 동안 텍스트가 보이도록 하라는 것인데, 이렇게 lighthouse에서도 웹 폰트 최적화를 하라고 알려준다.

import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
    * {
        margin:0;
        padding:0;
        font-family: Cafe24ClassicType-Regular;
    }
    @font-face {
        font-family: 'Cafe24ClassicType-Regular';
        src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2210-2@1.0/Cafe24ClassicType-Regular.woff2') format('woff2');
        font-weight: normal;
        font-style: normal;
        font-display:swap;
    }
`;

export default GlobalStyle;

위와 같이 font-display에 swap 속성 값을 주었더니 lighthouse에서 더 이상 폰트 최적화에 관한 알림이 뜨지 않았으며, 퍼포먼스 점수 또한 올라갔다.

참고 :
https://d2.naver.com/helloworld/4969726
https://whales.tistory.com/66
https://velog.io/@vnthf/%EC%9B%B9%ED%8F%B0%ED%8A%B8-%EC%B5%9C%EC%A0%81%ED%99%94-%ED%95%98%EA%B8%B0

profile
유능한 프론트엔드 개발자가 되고픈 사람😀

1개의 댓글

comment-user-thumbnail
2024년 3월 29일

도움 많이 되었습니다 감사합니다 :)

답글 달기