WEB

웹 폰트와 최적화

ㅇㄱ9 2021. 11. 30. 20:00
728x90

프로젝트에서 사용하는 웹폰트 용량이 커서 화면 렌더링 속도가 지연되는 경우가 있다.

이를 최적화 하는 방법을 알아보자. 

웹폰트란? 

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

 

웹 폰트는 font-family 속성을 사용하고, @font-face를 통해 웹 브라우저에게 해당 서체를 다운로드할 것임을 알리면서 사용할 수 있다. 

 

[출처] https://d2.naver.com/helloworld/4969726

- font-family

사용할 웹 폰트의 이름을 지정한다. 이 이름은 폰트 파일의 이름과 일치하지 않아도 상관없지만 비슷하게 설정하는 것이 유지보수에 좋다. 

 

- src 

폰트 파일의 경로와 폰트의 형식을 지정한다. url에 폰트 파일의 경로를 설정하고, format에 폰트 파일의 현식을 설정한다. 

 

- fallback 폰트 

지정한 웹 폰트 로딩이 실패하면 다음에 선언된 폰트가 렌더링 된다. 

 

웹폰트 파일 관리

- 서버에 직접 업로드

CSS에 @font-face를 직접 선언해 준다. 폰트 종류가 많을수록 @font-face를 많이 선언해야하지만 브라우저에 따라 코드를 추가, 삭제할 수 있다. 또한 CDN을 사용하는것보다 속도가 빠르고 안전하다.

<!-- font.html -->
<head>
 <link rel="stylesheet" href="style.css">
</head>
<body>
 <h1>안녕하세요</h1>
</body>
/* style.css */
@font-face {
 font-family: NanumSquareWeb;
 src: url(../webfont/NanumSquareR.eot);
 src: url(../webfont/NanumSquareR.eot?#iefix) format('embedded-opentype'),
 url(../webfont/NanumSquareR.woff2) format('woff2'),
 url(../webfont/NanumSquareR.woff) format('woff'),
 url(../webfont/NanumSquareR.ttf) format('truetype');
}
h1 {
 font-family: NanumSquareWeb, sans-serif;
}

코드출처

:https://velog.io/@kim-jaemin420/Web-font%EC%9B%B9-%ED%8F%B0%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C

 

- CDN 사용

별도의 @font-face를 지정하지 않아도 되기 때문에 편리하지만 서버에 직접 업로드 하는것보다 속도가 느리고 CDN서버가 제대로 동작하지 않을 때는 웹폰트를 제공받지 못할 수 있다. 

구글 CDN의 경우 @font-face에 WOFF와 WOFF2만 지원하므로 IE 6~8, IE 호환성 보기 모드에서는 웹폰트를 사용할 수 없다.

<!-- font.html -->
<head>
 <link rel="stylesheet" href="//fonts.googleapis.com/earlyaccess/notosanskr.css">
 <link rel="stylesheet" href="style.css">
</head>
<body>
 <h1>안녕하세요</h1>
</body>
/* style.css */
h1 {
 font-family: 'Noto Sans KR', sans-serif;
}

코드출처

:https://velog.io/@kim-jaemin420/Web-font%EC%9B%B9-%ED%8F%B0%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C

 

기본 글꼴 깜빡임 현상

웹 폰트를 아직 다 다운로드하기 전에, 기본 글꼴로 콘텐츠가 표시됐다가 웹 폰트를 다 다운로드하면 웹 폰트로 전환되면서 내용이 한 번 깜빡이는 현상을 말한다. FOUT, FOIT, FOFT 의 해결책들이 있다. 

 

현재는 모든 주요 브라우저가 FOIT로 불리는 해결책을 적용한 상태다. (IE는 FOUT방식)

  • FOIT: 웹폰트가 적용된 텍스트 영역을 여백으로 처리하고, 웹폰트 로딩이 완료되면 해당 폰트를 적용한다. 단, 3초의 제한 시간이 있어 로딩이 3초를 넘어가면 폴백 폰트로 렌더링 한다. 한국어 웹 폰트는 용량이 커서, 다운로드 속도가 느리면 아주 오랫동안 화면이 비어 있게 된다.
  • FOUT: 폴백 폰트를 먼저 표시하고, 웹폰트 로딩이 완료되면 해당 폰트를 적용한다.

[출처]&amp;amp;nbsp;https://d2.naver.com/helloworld/4969726

로컬 스토리지에 폰트를 캐시했다가 꺼내 쓰는 것은, 브라우저의 캐시를 꺼내 쓰는 것보다 꽤 느린데, 대신 훨씬 안정적이다. 

 

FOUT를 방지하기 위해 웹폰트를 불러오는 자바스크립트 코드는 <head>에 두고 이때 자바스크립트는 로컬 스토리지 글꼴 저장 여부를 알아낸다. 저장하지 않았다면 우선 페이지를 렌더링한 뒤, base64로 인코딩한 woff 글꼴을 내장한 CSS 파일 내용을 ajax로 가져와 <head>에 뿌리고, 그걸 로컬 스토리지에 저장한다. FOUT는 이 때 한 번 일어난다.

이후 방문에서는 localStorage에 저장된 CSS 내용을 꺼내서 <head>에 박기 때문에 FOUT가 일어나지 않는다.

텍스트 렌더링 

브라우저는 텍스트를 렌더링 하기 위한 글꼴 리소스를 알기 전에 DOM과 CSSOM트리에 의존하는 렌더트리를 구성해야한다. 따라서 글꼴 요청은 다른 중요한 리소스 이후에 수행하게되며 리소스를 가져 올때 까지 브라우저가 텍스트 렌더링을 차단할 수 있다. 

 

렌더링이 늦어지는 경우 아래와 같이 특정 글자가 보이지 않고 의미전달이 완전히 잘못될 수 있다. 

[출처] https://www.zachleat.com/web/mitt-romney-webfont-problem/

 

다음은 웹 폰트를 렌더링 하는 과정이다. 

1) 브라우저가 HTML문서를 요청한다. 

2) HTML 응답을 구문 분석하고 DOM을 구성하기 시작한다.

3) 브라우저는 CSS, JS 및 기타 리소스를 검색하고 요청을 디스패치한다.

4) 브라우저는 모든 CSS 콘텐츠를 수신한 후 CSSOM을 생성하고, 렌더 트리를 생성하기 위해 DOM 트리와 결합한다.

- 글꼴 요청은 렌더 트리가 페이지에서 지정된 텍스트를 렌더링하는 데 필요한 글꼴 변형을 표시한 후에 발송된다.

5) 브라우저가 레이아웃을 수행하고 화면에 콘텐츠를 그린다.
- 글꼴을 아직 사용할 수 없는 경우 브라우저가 텍스트 픽셀을 렌더링하지 못할 수 있고, 글꼴을 사용할 수 있게 되면 브라우저가 텍스트 픽셀을 그린다.

페이지 내용의 첫 번째 페인트의 "race"는 렌더 트리가 만들어진 직후 수행될 수 있으며 글꼴 리소스에 대한 요청은 브라우저가 페이지 레이아웃을 렌더링하지만 텍스트를 생략하는 "빈 텍스트 문제"를 발생시킨다.

WebFonts를 미리 로드하고 font-display를 사용하여 브라우저가 사용할 수 없는 글꼴인 경우를 제어하면 글꼴 로드로 인한 빈 페이지 및 레이아웃 변경을 방지할 수 있다. 

 

웹 폰트 최적화

- 폰트 파일의 용량 줄이기

  • 압축된 폰트 형식 사용
    폰트 형식에서 WOFF(Web Open Font Format) 형식과 WOFF 2.0 형식(이하 WOFF2 형식)은 압축된 폰트 형식이다. 같은 계열에 속하는 WOFF 형식과 WOFF2 형식에서는 WOFF2 형식이 30~50% 더 압축된 형식이다.

[출처]&amp;amp;nbsp;https://d2.naver.com/helloworld/4969726

  • 서브셋 폰트
    서브셋 폰트(subset font)는 폰트 파일에서 불필요한 글자를 제거하고 사용할 글자만 남겨둔 폰트다.
    영어는 26개 알파벳으로 이루어져 있다. 영문 폰트에는 대소문자를 포함해 총 72자의 글자가 필요하다. 하지만 한글은 자음, 모음의 조합으로 구성되어 있다. 모든 경우를 조합하면 한글의 글자 수는 11,172자나 된다. 그래서 한글 폰트 파일은 영문 폰트 파일보다 용량이 크다.
    [출처]&amp;amp;nbsp;https://d2.naver.com/helloworld/4969726
    노란색으로 표시된 글자들은 거의 사용하지 않는 글자들로 이를 제외하면 나눔바른고딕 폰트기준으로 한글 글자를 11,172자(2.4MB)에서 2,350자(586KB)로 줄여 서브셋 폰트를 만들 수 있다. 

- WebFont 리소스 사전 로드

<link rel="preload">를 사용하면 CSSOM이 생성될 때까지 기다릴 필요 없이 중요한 렌더링 경로의 초기에 WebFont에 대한 요청을 트리거할 수 있다. 즉, CSS 파일보다 먼저 웹 폰트 파일의 다운로드를 시작한다. 

 

- 텍스트 렌더링 지연 사용자 지정

사전 로드는 페이지의 내용이 렌더링될 때 WebFont를 사용할 수 있는 가능성을 높이지만 보장하지는 않는다. 이때 font-display를 사용하여 최신 브라우저에 원하는 동작을 지정할 수 있다. 동일한 환경에서는 렌더링도 더 빨리 끝난다. 로딩이 빠르기 때문에 렌더링 차단 시간 역시 줄어든다.

 

일부 브라우저가 구현하는 기존의 글꼴 시간 초과 동작과 유사하게 font-display는 글꼴 다운로드의 수명을 세 가지 주요 기간으로 나눈다.

 

  1. 글꼴 차단 기간 (font block period)
    이 기간 동안 font face을 로드하지 않으면 font face을 사용하려는 요소가 보이지 않는 대체 font face을 렌더링해야 합니다. 이 기간 동안 font face가 성공적으로 로드되면 font face가 정상적으로 사용됩니다.
  2. 글꼴 스왑 기간 (font swap period)
    글꼴 차단 기간 직후에 발생합니다. 이 기간 동안 font face을 로드하지 않으면 font face을 사용하려는 요소가 대체 font face을 렌더링해야 합니다. 스왑 기간 동안 font face가 성공적으로 로드되면 font face가 정상적으로 사용됩니다.

  3. 글꼴 오류 기간 (font failure period)
    글꼴 스왑 기간 직후에 발생합니다. 이 기간이 시작될 때 font face가 아직 로드되지 않은 경우 실패한 로드로 표시되어 정상적인 글꼴 대체가 발생합니다. 그렇지 않으면 글꼴이 정상적으로 사용됩니다.
@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

font-display 속성은 다음과 같이 auto, block, swap, fallback, optional의 5가지 옵션이 있다.

  • block : FOIT와 동일하게 작동하는 옵션이다. 웹 폰트가 로딩되지 않았을 때는 텍스트를 렌더링하지 않는다(최대 3초). 웹 폰트 로딩이 완료되면 웹 폰트를 적용한다.
    font-display: block &amp;amp;nbsp;속성 작동 방식 [출처]&amp;amp;nbsp;https://d2.naver.com/helloworld/4969726&amp;amp;nbsp;
  • swap : FOUT와 동일하게 작동하는 옵션이다. 우선 폴백 폰트로 글자를 렌더링하고, 웹 폰트 로딩이 완료되면 웹 폰트를 적용한다. 웹 폰트 로딩 여부와 관계없이 항상 텍스트가 보인다.
    font-display: swap &amp;amp;nbsp;속성 작동 방식 [출처]&amp;amp;nbsp;https://d2.naver.com/helloworld/4969726
  •      fallback : 이 옵션을 사용하면 우선 100ms 동안 텍스트가 보이지 않고, 그 후 폴백 폰트로 렌더링한다. 특이한 점은 약 2초의 전환(swap) 시간이 있다는 점이다. 이 시간 안에 로딩이 완료되면 웹 폰트로 전환한다. 하지만 이 시간이 지나면 웹 폰트 다운로드가 완료되어도 웹 폰트로 전환하지 않고 폴백 폰트를 유지한다.
    전환 시간 이후에 다운로드된 웹 폰트는 웹 페이지에 적용되지는 않지만 캐시에는 저장된다. 그래서 추후에 사용자가 다시 방문했을 때 바로 웹 폰트가 적용된다는 장점이 있다.

  • optional : 우선 100ms 동안 텍스트가 보이지 않고 그 후 폴백 폰트로 전환한다. 웹 폰트를 다운로드하지만 브라우저가 네트워크 상태를 파악해 웹 폰트 전환 여부를 결정한다는 점이 이 옵션의 특이한 점이다. 예를 들어 네트워크의 연결 상태가 안 좋으면 웹 폰트의 다운로드가 완료되어도 캐시에 저장만 하고 전환은 하지 않는다.
    font-display: optional &amp;amp;nbsp;속성 작동 방식 [출처] https://d2.naver.com/helloworld/4969726

 

-- 

참고

1) https://velog.io/@kim-jaemin420/Web-font%EC%9B%B9-%ED%8F%B0%ED%8A%B8%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C

2) https://d2.naver.com/helloworld/4969726

3) https://web.dev/optimize-webfont-loading/

4) https://web.dev/reduce-webfont-size/

5) https://mytory.net/2016/06/15/webfont-best-practice.html

6) https://armadillo-dev.github.io/html/css/webfont-optimize/

728x90
반응형