본문 바로가기
OS & Network

웹 최적화 - 구글 폰트 속도 빠르게 만들기 (Making Google Font Faster In 2022)

by 새발개발JA 2022. 12. 13.
반응형

얼마전 웹사이트 속도를 측정하면서 구글폰트에 많은 시간을 할애한다는 것을 발견했다.

개선을 위해 이 아티클을 읽게 되었고, 아티클 기반으로 직접 테스트도 해본 과정을 포스팅해보려고 한다.

 

 

다음은 폰트 최적화를 위한 노력의 과정을 순서대로 담은 포스팅이다 :)

 

1. 구글 폰트 속도 빠르게 만들기 (Making Google Font Faster In 2022) - 이론을 먼저 공부해보자

 

웹 최적화 - 구글 폰트 속도 빠르게 만들기 (번역)

얼마전 웹사이트 속도를 측정하면서 구글폰트에 많은 시간을 할애한다는 것을 발견했다. 개선을 위해 이 아티클을 읽게 되었고, 아티클 기반으로 직접 테스트도 해본 과정을 포스팅해보려고 한

devbirdfeet.tistory.com

 

2. 구글 폰트 속도 빠르게 만들기 (TEST)  - 이론을 바탕으로 실서비스 사이트를 개선해보자

 

웹 최적화 - 구글 폰트 속도 빠르게 만들기 (TEST)

웹 사이트의 성능을 측정해 보았더니 구글 폰트를 다운 받는데 시간이 꽤 걸렸다. 브라우저 렌더링을 할 때, 폰트 다운로드가 끝날때까지 기다렸다가 다음 태그를 읽어와서 그런 것 같았다. 참

devbirdfeet.tistory.com

 

 

 


웹 최적화 - 구글 폰트 속도 빠르게 만들기

결국 틈날 때마다 정독하다 내가 필요한 지식들 위주로 아티클을 번역/정리 해버렸다.

구글 폰트 속도를 빠르게 만들어 보자

Anatomy of a Google Fonts request

우리는 보통 <link> 태그를 통해 구글 폰트를 다운받는다. <link> 를 통해 구글폰트를 다운받는 과정을 알아보자.

<link href="https://fonts.googleapis.com/css?family=Muli:400" rel="stylesheet"/>

 

<link> 를 통해 구글 폰트 를 로드하면 → @font-face 가 선언된 stylesheet 가 로드된다.

(요 @font-face 에는 사용가능한 모든 글자 별로 set 된 모든 폰트 스타일이 선언되어 있다)

 

이 @font-face 는 구글폰트를 다운받는 동안 내장폰트를 사용하라고 브라우저에게 명령한다.

(즉, 로딩이 길어지면 유저는 텅빈 화면만 보게 되므로 대체폰트로 보여주다가 구글폰트 다운이 끝나면 싹 바뀌는 방식인 것이다.)

 If we load the link’s href into our browser, we see that Google Fonts loads a stylesheet of @font-face declarations for all the font styles that we requested in every character set that is available. 
 each @font-face declaration tells the browser to use a local version of the font, if available, before attempting to download the file from fonts.gstatic.com:

 


Should I use <link> or @import?

구글폰트 다운로드에는 @import 혹은 <link> 이렇게 두가지 옵션이 있다. 

둘중에 어떤 방법을 사용하는 것이 좋을가? <link> 를 추천한다.

@import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");

<link href="https://fonts.googleapis.com/css?family=Muli:400" rel="stylesheet"/>

 

@import 를 선언하게 되면 폰트는 css 파일과 함께 다운로드 된다. (css 파일 내에서 선언하기 때문) 

network 탭의 waterfall 을 살펴보면 각 요청은 체이닝된다.

HTML 이 로드되면 style.css 를 부르고 → 얘가 CSSOM 을 생성하고 나서야 구글폰트 다운로드가 되는 것이다.

 

하지만 <head> 안에서 <link> 로 폰트 다운로드를 하면, 속도는 더 빨라진다.

체이닝 단계가 하나 더 줄기 때문이다. (HTML DOM 파싱 단계에서 다운로드되기 때문)

In the network waterfall, we can see that each request is chained - the HTML is loaded on line 1, which triggers a call to style.css. Only after style.css is loaded and the CSSOM is created will the CSS from Google fonts then be triggered for download. And as we learned in the previous section, that file must also be downloaded and read before the fonts themselves will be downloaded.
By moving our font request to the <head> of our HTML instead, we can make our load faster because we've reduced the number of links in the chain for getting our font files:

 


Warm up that connection faster with preconnect

Network waterfall 을 보면 구글 폰트를 다운받을 때 2개의 호스트에 2가지 요청을 보낸다.

font.googleapis.com 의 stylesheetfont.gstatic.com 의 각 폰트의 unique URL 을 받아온다.

 

"Why can’t I just use the direct link to the font?"

구글 폰트는 업데이트가 빠르기 때문에 직접 다운 받아오면 그 링크가 사라질 수도 있기 때문이다.

 

<link rel="preconnect">를 사용해서 연결시간을 단축시키자

소켓이 필요로하기 전에 DNS lookup, TCP handshake, TLS negotiation 를 미리 해서 waterfall을 앞당길 수 있다.

connection 을 미리 해놓지 않으면 브라우저는 css가 폰트파일을 가져올 때까지 기다리게 된다.

<link rel="preconnect" href="https://fonts.gstatic.com" />

 

** <link> 의 rel 속성은 현재 문서와 외부 리소스 사이의 연관 관계를 명시한다.

** socket 은 두 프로그램이 네트워크를 통해 서로 통신을 수행할 수 있도록 양쪽에 생성되는 링크의 단자인데,

두 소켓이 연결되면 서로 다른 프로세스끼리 데이터를 전달할 수 있다.

We can make one quick performance improvement by warming up the DNS lookup, TCP handshake, and TLS negotiation to the fonts.gstatic.com domain with preconnect:
By adding the preconnect, we can perform DNS/TCP/TLS before the socket is needed, thereby moving forward that branch of the waterfall:

 


Flash of Invisible text and the font-display property

 

글꼴은 대용량 파일인 경우가 많아서 일부 브라우저는 글꼴이 로드될 때까지 텍스트를 숨긴다.

래서 보이지 않는 텍스트의 깜박임(FOIT) 이나 스타일이 지정되지 않은 텍스트의 깜박임(FOUT) 이 생긴다.

 

@font-face 를 선언할때 font-display 의 옵션들을 사용해보자

이 옵션은 폰트가 로딩되는 동안 font-display를 어떻게 할건지를 control 하게 된다.

font-display:
	auto     // The font display strategy is defined by the user agent.
	block    // Gives the font face a short block period and an infinite swap period.
	swap     // Gives the font face an extremely small block period and an infinite swap period
	fallback // Gives the font face an extremely small block period and a short swap period.
	optional // Gives the font face an extremely small block period and no swap period.

 

<link> 에서 폰트를 다운받을 때 이 속성을 적용하려면 API 뒤에 쿼리로 넣으면 된다.

<link rel="stylesheet" href="https://fonts.googleapis.com/css2?display=swap">

 


Self-host your web fonts for full control

구글 폰트를 CDN 에서 직접 호스팅할 수는 없을까?

폰트를 직접 호스팅 하는게 속도를 빠르게 하진 않는다. (CDN은 제외하고)

하지만 폰트 파일, 로딩, css 들까지 모두 컨트롤 하려면 셀프 호스팅 할 수 있다.

 

→ 즉, 폰트 파일을 직접 다운받아서 우리가 CDN 에 폰트파일을 저장해서 웹사이트로 날리는 방법을 의미한다.

 

**아래 사이트에서 구글 폰트 파일을 다운받을 수 있다. (@font-face 도 커스텀해서 바로 사용가능하다)

 

google webfonts helper

 

gwfh.mranftl.com

 

 

 


How to use preload to load fonts faster

브라우저는 필요하지 않은 폰트는 로드하지 않는다.

하지만 폰트가 (무조건) 사용될 페이지이면, preload 해주자. 더 빨라질 것이다.

 

<link rel="preload">

브라우저에서 선언적으로 리소스를 가져오지만 실행은 하지 않는다. (대기열추가)

 

<link as="font">

브라우저에 font 가 다운로드된다는 것을 알려준다.

적절한 우선순위를 가지게 된다. 이게없으면 default로 낮은 우선순위가 된다.

 

<link type="font/woff2">

브라우저에 파일 타입을 알려준다. 파일타입에 맞는 리소스만 다운로드한다.

 

<link crossorigin> 폰트를 패치할때 CORS 익명모드를 사용하기 때문에 CORS 에러를 피하기위해 필요하다

 <link
    rel="preload"
    as="font"
    type="font/woff2"
    href="./fonts/muli-v12-latin-regular.woff2"
    crossorigin
 />
Once we know we definitely need a particular font on a page, we can preload it with the preload resource hint:
Before we go any further, make sure you understand that `preload` will load a resource whether you use it or not.

** preload  옵션은 사용하든 안하든 리소스를 무조건 로드하니 꼭 필요한데서만 로드하도록 주의하자

 

 

 


Oh no, preload made my page's initial render slower!

preload된 파일은 초기렌더에 필요한 중요한 파일들 보다 먼저 로드된다.

만약 preload된 파일 갯수가 많다면  초기 렌더링을 느리게 만들 수 있다.

 

좋은 전략은 preload할 부분을  4 - 5개 이하로 줄이는 것이다.

예를 들면 main dish 급의 스타일이랑 캐릭터셋을 선택해서 걔네만 먼저 preload 를 한다.

그리고 나머지는 preload 를 쓰지말고 필요에 따라 로드하면 된다.

 

@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 400;
  src: local("Open Sans Regular"), local("OpenSans-Regular"), url(https://fonts.gstatic.com/s/opensans/v15/mem8YaGs126MiZpBA-UFVZ0bf8pkAg.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

 

Preloaded files are currently loaded before other, more important files needed for initial render.
Your best strategy is to minimize how many resources you preload and TEST, TEST, TEST
Generally speaking, keep your preloads under 4-5, and preferably even lower. 
You could choose to only preload your most used styles and character sets.

 

 


What are my options if I don't preload? 

속도의 차이는 폰트를 어느 시점에 다운받느냐에 따라 달라진다. 왜냐하면 폰트를 다운받는 동안 delay 되기 때문이다.

 

preload로 미리 다운받아버리는 방법이 있지만,

폰트가 (무조건) 사용된다는 전제 하에 유용한 방법이라서 폰트를 사용 안 하게되면 삭제해줘야 된다.

HTML이 로드될 때 <head> 안에 <style>로 font-face 와 font-style 을 넣어주면 함께 로드가 될것이다.

(보통은 CSSOM 이 만들어지길 기다려야 하는데 시간이 걸린다)

 

이때 직접 넣어주는 건 필자는 추천하지 않으며 css추출에 대해서는 아래 포스팅 참고를 권한다.

 

중요한 CSS 추출

중요한 CSS 기술로 렌더링 시간을 개선하는 방법과 프로젝트에 가장 적합한 도구를 선택하는 방법에 대해 알아보세요.

web.dev

 

 

 

 

 

 

 

ref: https://sia.codes/posts/making-google-fonts-faster/

 

Sia Karamalegos, Web Performance

Performance engineer and web developer, speaker, teacher, community organizer, and Google Developers Expert in Web Technologies based in Durham, North Carolina

sia.codes

 

 

반응형

댓글