웹 개발을 하다보면 빼 놓을 수 없는 요소 중 하나인 폰트에 대해 알아보자.
폰트는 크게 웹 폰트와 로컬 폰트, 이 두 가지로 나눌 수 있다.
로컬 폰트
: 로컬 컴퓨터에 설치되어 있는 폰트
로컬 폰트 적용 방법
@font-face
활용
<a-remote-font-name>
: 폰트명으로 지정될 이름<source>
: 원격 폰트 파일의 위치를 나타내는 url 값을 지정하거나, 로컬 환경에 있는 폰트명을local("Font Name")
형식으로 지정- 만약 로컬 환경에 있는 폰트를 지정하려면
src: local('Font Name')
과 같은 형식으로 폰트 지정@font-face { font-family: <a-remote-font-name>; src: <source> [,<source>]*; [font-weight: <weight>]; // font 굵기 값 [font-style: <style>]; // font 스타일 값 }
웹 폰트
: 로컬 폰트의 설치 여부와 상관없이 온라인의 특정 서버에 위치한 폰트 파일을 다운로드하여 화면에 표시해주는 웹 전용 폰트
웹 폰트 적용 방법
대표적인 예시는 Google Font이다.①
<link>
활용<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100&family=Open+Sans:wght@400;600;700&display=swap" rel="stylesheet">
②
@import
활용<style> @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@100&family=Open+Sans:wght@400;600;700&display=swap'); </style>
이 둘은 로딩 속도에서 큰 차이를 보인다. 로컬 폰트는 이미 설치되어 있는 파일을 사용하기 때문에 속도가 빠르고, 웹 폰트는 새로 다운을 받아야 하기 때문에 로컬 폰트에 비해 느리다. 이로 해 웹 폰트를 사용하면 FOIT, FOUT 현상이 발생하기도 한다.
FOIT (Flash Of Invisible Text)
: 브라우저가 폰트를 다운로드하기 전까지 글자가 보이지 않는 것
➜ 글자 자체가 보이지 않음
FOUT (Flash Of Unstyled Text)
: 브라우저가 폰트를 다운로드하기 전까지 폰트가 적용되지 않는 것
➜ 초기화된 폰트로 글자가 보임
그러나, 로컬 폰트는 설치되어있지 않은 경우 디자인이 깨져 보일 수 있다는 치명적인 단점이 있다.
이로 인해 디자인이 깨질 염려는 없는 웹 폰트를 주로 사용하며, 느린 속도를 보완하기 위한 방법인 Preload 옵션을 활용한다.
<link rel="preload" href="./nanumGothic.woff2" as="font" type="font/woff2" crossorigin="anonymous">
위와 같이 태그의 rel="preload"을 사용하면 해당 리소스를 다른 리소스보다 빨리 로딩한다. 폰트 파일 이외에도 이미지 파일, 스크립트 파일, 비디오 파일 등 페이지에서 중요도가 높은 자원을 의도적으로 먼저 로딩할 때 preload 옵션을 사용한다.
이는 미리 다운로드 해 놓음으로써, 사이트에 방문할 때마다 새로 렌더링하지 않아도 돼 속도를 향상시킬 수 있다.
그러나, preload 옵션으로 다운로드하는 리소스가 많아질수록 처음 렌더링 시간이 늦어진다는 문제가 있다. 그렇기 때문에 현재 페이지에서 중요도가 높고 먼저 렌더링되어야 하는 리소스만 preload 옵션으로 지정하는 것이 좋다.
더불어 이러한 preload 방식 말고도, 다양한 웹 폰트 최적화 방법을 사용해 웹 폰트의 용량과 텍스트가 보이지 않는 문제 등을 해결할 수 있다.
1. 웹 폰트 형식 사용하기
아래와 같이 TTF/OTF, WOFF, WOFF2, SVG, EOT 형식이 있다. 브라우저 별로 지원하는 웹폰트가 다르니 확인 후 적용하면 된다.WOFF과 WOFF2는 압축된 폰트 형식이다. 같은 계열에 속하는 WOFF 과 WOFF2 중, WOFF2가 30~50% 더 압축된 형식이다.
WOFF2는 IE 브라우저를 제외한 모든 브라우저에서 사용할 수 있는데,
IE 브라우저는 단종되었으니모든 브라우저에서 WOFF2 형식을 사용하도록 해서 폰트의 용량을 줄일 수 있다.
출처 : W3Schools
2. 서브셋 폰트 사용하기
한글의 자음과 모음의 모든 경우를 조합하면 글자 수는 11,172자나 된다. 이로 인해 한글 폰트 파일은 영문 폰트 파일보다 용량이 크다.그러나 갃, 갧, 냛, 춃, 뫭, ... 이런 조합들은 평소에 사용하지 않으니, 이런 글자들을 제거하고 사용할 글자만 남겨둔 폰트를 서브셋 폰트라고 한다.
최근에 출시되는 한글 웹 폰트의 대부분은 2,350자의 서브셋 폰트라고 한다.
3. unicode-range 속성 사용하기
: 유니코드로 지정한 글자에만 웹 폰트를 적용하는 속성등록된 글자가 텍스트에 없으면 웹 폰트 다운로드를 요청하지 않는다는 장점이 있다. 즉, 웹 폰트를 사용하지 않으면 불필요한 다운로드를 막을 수 있다.
@font-face { font-family: NanumPenWeb; src: url(NanumPenWeb.woff2) format('woff2'); unicodde-range: U+BC14, U+CC28;
위 코드가 적용된 모습 ↓
출처 : Naver D2
1. Font Face Observer 라이브러리 사용하기
: 웹 폰트의 로딩 상태를 추적할 수 있는 폰트 로더파일 크기가 작고 실행 속도가 빠르다는 장점이 있다.
/*CSS*/ // 로드 전 body { font-family: 'Apple SD Gothic Neo', sans-serif; } // 로드 후 body.font-loaded { font-family: 'Roboto', 'Apple SD Gothic Neo', sans-serif; }
CSS에 웹 폰트를 적용하지 않은 상태와 적용한 상태를 선언해 두고, 적용하지 않은 상태의 CSS가 먼저 적용되도록 한다.
/*JS*/ // 사용할 웹 폰트 추적 var font = new FontFaceObserver('Roboto'); // 로드 후, 클래스 추가 font.load().then(funtion(){ document.body.classList.add('fonts-loaded'); });
JS에 사용할 웹 폰트의 이름을 파라미터로 하는 FontFaceObserver(웹 폰트의 로딩 상태를 추적하는) 객체를 생성한다. 그리고 load() 메서드를 사용해 웹 폰트의 로딩이 완료되면 CSS 클래스가 추가되도록 한다.
이렇게 설정하면 처음에는 폴백 폰트를 설정한 CSS가 적용된다. 그리고 웹 폰트의 로딩이 완료되면 웹 폰트를 설정한 CSS가 적용된다. 마치 FOUT 방식처럼 작동하는 것이다.
출처 : Naver D2
2. font-display 속성 사용하기
외부 라이브러리를 사용하지 않아도 웹 폰트의 로딩 상태에 따른 동작을 설정할 수 있다.auto, block, swap, fallback, optional의 5가지 옵션이 있다. (자세한 설명은? MDN)
텍스트가 항상 보이게 하려면 FOUT와 동일하게 작동하는 swap 옵션을 사용한다. fallback 옵션과 optional 옵션을 사용하면 100ms 동안 텍스트가 보이지 않지만 매우 짧은 시간이어서 이 옵션들도 최적화에 사용할 수 있다.
font preload만 정리하려고 했던 글이 찾아볼수록 범위가 넓어져서 로컬 폰트와의 비교부터 preload 사용 방법, 그 외의 폰트 최적화 방법까지 정리하는 글이 되었다. 최적화 방법은 기재된 것 말고도 더 많은 방법이 있을 것으로 예상된다. 만약 알게 된다면 정리하기 위해 추가할 것 같다.