1. 웹폰트란?
방문자의 로컬 컴퓨터에 폰트 설치 여부와 상관 없이 온라인의 특정 서버에 위치한 폰트 파일을 다운로드하여 화면에 표시해주는 웹 전용 폰트입니다.
예를 들면, 웹폰트를 사용하지 않았을 경우 나눔고딕 폰트 미설치 PC에서는 기본 폰트인 돋움 폰트가 노출되고 나눔고딕 폰트 설치 PC에서는 나눔고딕 폰트가 노출됩니다.
하지만 웹폰트를 사용할 경우에는 나눔고딕 폰트 설치 유무와 상관 없이 나눔고딕 폰트가 노출됩니다.
2. 웹폰트를 사용하기 위해 알아야 @font-face 속성
@font-face {
font-family: NanumSquareWeb;
src: local(NanumSquareR),
local(NanumSquare),
url(NanumSquareR.eot?#iefix) format('embedded-opentype'),
url(NanumSquareR.woff) format('woff'),
url(NanumSquareR.ttf) format('truetype');
font-style: normal;
font-weight: normal;
unicode-range: U+0-10FFFF;
}
h1 {
font-family: NanumSquareWeb, sans-serif;
}
나눔스퀘어 폰트를 웹폰트로 사용하려고 위의 코드처럼 @font-face를 적용합니다. @font-face에는 font-family, src, font-style, font-weight, unicode-range 속성을 사용할 수 있습니다.
2-1. font-family
CSS 문서에서 사용할 웹폰트 패밀리명 입니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.woff) format('woff')
}
위의 코드는 ‘내가 사용할 웹폰트 패밀리명을 NanumSquareWeb으로 하겠다’ 라고 선언한 예 입니다.
font-family에서 선언한 웹폰트 패밀리명과 사용할 웹폰트 명이 반드시 같아야 하는 것은 아닙니다.
@font-face {
font-family: '블로그 제목';
src: url(NanumSquareR.woff) format('woff')
}
위의 코드처럼 웹폰트 패밀리명을 ‘블로그 제목’으로 정하고 하고 나눔스퀘어 폰트를 사용해도 상관 없습니다. 하지만 유지보수를 위해서는 웹폰트 패밀리명과 사용할 폰트명을 동일하게 해주는 것이 좋습니다.
* IE 11 이하에서는 font-family에 선언한 웹폰트 패밀리명이 31자 이상이 되면 적용이 되지 않습니다(한글, 영문 모두). 그러므로 IE를 고려하려면 웹폰트 패밀리명을 정할 때에도 주의하셔야 합니다. 참고
2-2. src
로컬에 이미 설치 된 폰트의 경로를 적는 local() 속성과 다운로드 할 웹폰트의 주소를 적는 url() 속성이 있습니다. 두 속성 모두 콤마(,)를 사용하여 여러번 중첩해서 사용할 수 있으며 마지막에 오는 속성에 세미콜론만 붙여주면 됩니다.
브라우저에 적용할 수 있는 폰트를 찾을 때까지 선언한 순서대로 이동합니다.
@font-face {
font-family: NanumSquareWeb;
src: local(NanumSquareR), /* 첫번째 */
local(NanumSquare), /* 두번째 */
url(NanumSquareR.eot), /* 세번째 */
url(NanumSquareR.woff), /* 네번째 */
url(NanumSquareR.ttf); /* 다섯번째 */
}
위 코드는 local(NanumSquareR) → local(NanumSquare) → url(NanumSquareR.eot) → url(NanumSquareR.woff) → url(NanumSquareR.ttf) 순으로 폰트를 찾습니다.
만약 나눔스퀘어 폰트가 설치되지 않은 PC 사용자가 크롬브라우저를 통해 웹 사이트에 접속하면 local(NanumSquareR) → local(NanumSquare) → url(NanumSquareR.eot) → url(NanumSquareR.woff) 순으로 이동하여 NanumSquareR.woff 파일이 적용 됩니다. 왜냐하면 크롬브라우저에서는 .eot파일을 지원해주지 않기 때문입니다. 참고
즉, 불필요한 다운로드가 일어나게 됩니다.
이러한 불필요한 다운로드를 막기 위해서 format 속성을 사용합니다. format 속성을 사용하면 브라우저에서 지원 가능한 파일만 다운로드 받을 수 있습니다.
@font-face {
font-family: NanumSquareWeb;
src: local(NanumSquareR), /* 첫번째 */
local(NanumSquare), /* 두번째 */
url(NanumSquareR.eot) format('embedded-opentype'),
url(NanumSquareR.woff) format('woff'), /* 세번째 */
url(NanumSquareR.ttf) format('truetype'); /* 네번째 */
}
위의 코드로 변경하게 되면 지원 불가능한 .eot파일은 건너 뛰고 local(NanumSquareR) → local(NanumSquare) → url(NanumSquareR.woff) 순으로 이동하여 NanumSquareR.woff 파일이 적용 됩니다.
* IE 8 이하브라우저에서는 local() 속성을 인식하지 못하고, 사용자 로컬에 폰트가 잘 못 설치된 경우 원하는 화면이 노출되지 않을 수 있기 때문에 local() 속성을 대부분 사용하지 않습니다.
2-3. font-weight, font-style
폰트이름을 하나로 하고 여러개의 스타일을 표현하고자 할 때 사용합니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareL.woff) format('woff');
font-weight: 300;
}
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.woff) format('woff');
font-weight: 400;
}
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareB.woff) format('woff');
font-weight: 700;
}
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareEB.woff) format('woff');
font-weight: 800;
}
위의 코드를 보면 웹폰트 패밀리명은 NanumSquareWeb으로 하나지만 font-weight를 이용하여 사용할 웹폰트를 다르게 선언하고 있습니다.(@font-face에 적용한 font-weight는 일반적으로 사용되는 굵기에 대응하는 값을 적어주는 것이 좋습니다. 참고)
font-weight가 300일 경우에는 NanumSquareL.woff,
font-weight가 400일 경우에는 NanumSquareR.woff,
font-weight가 700일 경우에는 NanumSquareB.woff,
font-weight가 800일 경우에는 NanumSquareEB.woff 가 적용됩니다.
font-weight 200, font-weight 600은 선언이 안되있는데 font-weight: 200과 font-weight:600일 경우 어떤 웹폰트가 적용될까요?
h1 {
font-family: NanumSquareWeb, sans-serif;
font-weight: 200; /* ? */
}
h2 {
font-family: NanumSquareWeb, sans-serif;
font-weight: 600; /* ? */
}
만약 정확히 주어진 font-weight를 사용할 수 없다면 실제로 렌더링 되는 font-weight를 결정하기 위해 다음과 같은 규칙 적용 됩니다. 참고
- 만약 font-weight가 600 이상이면, 가능한 큰 font-weight 중 가장 가까운 font-weight가 적용됩니다.(만약 없다면 작은 font-weight 중 가까운 font-weight)
- 만약 font-weight가 300 이하이면, 가능한 작은 font-weight 중 가장 가까운 font-weight가 적용됩니다(만약 없다면 큰 font-weight 중 가까운 font-weight)
- 만약 font-weight가 400이면, 500이 적용되고 500이 없으면 300 이하일 때 규칙이 적용됩니다.
- 만약 font-weight가 500이면, 400이 적용되고 400이 없으면 300 이하일 때 규칙이 적용됩니다.
위의 규칙에 따르면 font-weight: 200은 가능한 작은 font-weight 중 가까운 font-weight: 300이 적용되어 NanumSquareL 폰트가 적용되고, font-weight: 600은 가능한 큰 font-weight 중 가까운 font-weight: 700이 적용되어 NanumSquareB가 적용됩니다.
h1 {
font-family: NanumSquareWeb, sans-serif;
font-weight: 200; /* NanumSquareL */
}
h2 {
font-family: NanumSquareWeb, sans-serif;
font-weight: 600; /* NanumSquareB */
}
* IE 8 이하에서 font-weight 관련된 이슈가 있습니다.
- font-weight: 100 ~ 500은 normal로 , font-weight: 600~900은 bold로 렌더링 됩니다.
- font-weight: 600이 적용되지 않을 수 있습니다.
이 이슈는 font-weight를 사용하지 않고 웹폰트 패밀리명을 굵기마다 각각 다르게 설정하면 해결할 수 있습니다.
@font-face {
font-family: NanumSquareWeb-Light;
src: url(NanumSquareL.woff) format('woff');
}
@font-face {
font-family: NanumSquareWeb-Regular;
src: url(NanumSquareR.woff) format('woff');
}
2-4. unicode-range
사용할 유니코드의 범위를 정합니다. 유니코드 범위 내 사용하는 문자가 없으면 웹폰트를 다운로드 하지 않습니다.(유니코드 표)
2-4-1. 단일코드
U+AC01 처럼 단일 유니코드를 사용할 수 있습니다. 콤마(,)를 이용해서 두 개 이상의 값도 넣을 수 있습니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareL.woff) format('woff');
unicode-range: U+AC01, U+AC08;
}
U+AC01은 ‘각’에 해당하고 U+AC08은 ‘갈’에 해당하므로 ‘각’과 ‘갈’ 부분이 변경되었습니다.
2-4-2. 범위코드
‘-‘ 를 이용하여 유니코드 범위를 설정하여 사용할 수 있습니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareL.woff) format('woff');
unicode-range: U+AC07-AC0A, U+AC00;
}
U+AC07-AC0A는 ‘갇갈갉갊’에 해당하고 U+AC00은 ‘가’에 해당하므로 ‘갇갈갉갊’과 ‘가’ 부분이 변경되었습니다.
2-4-3. 와일드카드
‘?’를 이용하여 유니코드 범위를 설정할 수 있습니다. ‘?’는 임의의 16진수 중 하나로 0 ~ F 의 값이 들어갈 수 있습니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareL.woff) format('woff');
unicode-range: U+003?;
}
U+003? 는 U+0030, U+0031, U+0032, … , U+003E, U+003F 이고 U+0030-003F 입니다. 그러므로 범위에 해당하는 ‘0123456789:;<=>?’ 부분이 변경되었습니다.
2-4-4. 사용법
unicode-range는 네이버 사전처럼 다국어를 지원해주는 사이트에서 웹폰트를 적용할 때 사용하면 좋습니다.
왼쪽 그림과 오른쪽 그림은 동일한 UI를 사용하고 있는 아랍어 사전, 캄보디아어 사전 입니다.
아랍어 사전일 때는 아랍어에 해당하는 웹폰트를 다운로드 하면 되고, 캄보디아어 사전일 때는 캄보디아어에 해당하는 웹폰트를 다운로드 하면 됩니다. 아랍어 사전일 때 캄보디아어에 해당하는 웹폰트를 다운로드 해도 적용할 수가 없어서 용량 낭비이기 때문입니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.woff) format('woff'); /* 나눔스퀘어 전체 */
unicode-range: U+06??; /* 아랍어 */
}
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.woff) format('woff'); /* 나눔스퀘어 전체 */
unicode-range: U+1780-17FF; /* 캄보디아어 */
}
만약 나눔스퀘어체가 모든 언어를 포함하고 있을 때, 위의 코드처럼 작성하면 될 것 같지만 잘못된 코드입니다. 아랍어를 사용해도 NanumSquareR.woff(3MB) 파일을 다운로드 하고 캄보디아어를 사용해도 NanumSquareR.woff(3MB) 파일을 다운로드 하기 때문입니다. unicode-range를 사용하지 않는 것과 같습니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR-Arab.woff) format('woff'); /* 나눔스퀘어 아랍어 부분 */
unicode-range: U+06??; /* 아랍어 */
}
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR-Cambodia.woff) format('woff'); /* 나눔스퀘어 아랍어 부분 */
unicode-range: U+1780-17FF; /* 캄보디아어 */
}
그래서 폰트 파일도 나누어야 합니다. 위의 코드를 보면 아랍어에 해당하는 유니코드에는 NanumSquareR-Arab.woff(14KB), 캄보디아어에 해당하는 유니코드에는 NanumSquareR-Cambodia.woff(7KB)를 url에 적용했습니다. 그래서 아랍어를 사용하는 곳에서는 NanumSquareR-Arab.woff(14KB)만 다운로드하고 캄보디아어를 사용하는 곳에서는 NanumSquareR-Cambodia.woff(7KB)만 다운로드 하게 됩니다.
NanumSquareR.woff(3MB)를 다운로드 하는 것 보다 많은 용량을 줄일 수 있습니다.
3. 브라우저별 대응 방법
위 그림을 보면 브라우저마다 지원하는 파일종류가 다르다는 것을 알 수 있습니다. EOT는 IE 브라우저만 지원을 하고 WOFF는 모든 브라우저에서 지원을 합니다. 그래서 모든 브라우저에서 웹폰트를 사용하려면 src 속성에 코드를 추가해야 합니다.
3-1. IE 6~8
IE 6~8은 EOT 파일만 지원하므로 EOT 파일을 내려받도록 해야합니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot) format('embedded-opentype'),
url(NanumSquareR.ttf) format('truetype');
}
위 코드처럼 작성하면 될 것 같지만 IE 6~8은 format(’embedded-opentype’) 처럼 포맷명을 해석하지 못합니다. 그래서 위의 코드는 다음과 같이 해석됩니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot%format('embedded-opentype')%url(NanumSquareR.ttf)%format('truetype'));
}
format 부분을 하나의 문자열로 인식하기 때문에 url에 긴 문자열이 들어가서 결국 Not Found가 발생합니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot?#iefix) format('embedded-opentype'), /* IE 6 ~ 8 */
url(NanumSquareR.ttf) format('truetype');
}
그래서 위 코드처럼 파일명 뒤에 물음표(?)를 추가합니다. 물음표 이후의 구문은 쿼리문으로 인식하기 때문에 모두 무시되어 NanumSquare.eot? 파일을 다운로드 하기 때문입니다.
3-2. IE 호환성 보기 모드
IE 호환성 보기 모드에서는 물음표(?) 속임수를 사용할 수 없습니다. 물음표(?)를 추가해도 format이 속성이 있거나 url이 속성이 한 번 더 사용된 경우 인식을 하지 못하기 때문입니다. 그래서 src를 따로 구분하여 별도 정의해 줍니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot); /* IE 호환성 보기 */
src: url(NanumSquareR.eot#iefix) format('embedded-opentype'), /* IE 6 ~ 8 */
url(NanumSquareR.ttf) format('truetype');
}
IE 6 ~ 8 에서 local() 속성을 인식하지 못하는 것을 이용하여 물음표(?) 속임수 대신에 스마일(☺)을 사용할 수 있습니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot); /* IE 호환성 보기 */
src: local(☺), /* IE 6 ~ 8 */
url(NanumSquareR.ttf) format('truetype');
}
3-3. 모던 브라우저
W3C의 표준을 비교적 빠르게 잘 반영하는 웹 브라우저(IE9+, Chrome, Safari, Opera..) 들은 WOFF를 지원합니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot); /* IE 호환성 보기 */
src: url(NanumSquareR.eot#iefix) format('embedded-opentype'), /* IE 6 ~ 8 */
url(NanumSquareR.woff) format('woff'), /* 모던 브라우저 */
url(NanumSquareR.ttf) format('truetype');
}
3-4. 구 모바일 브라우저
WOFF나 TTF 포맷을 지원하지 않던 몇몇 구 버전 모바일 웹 브라우저(예를들어 Safari 4.3 이하, Android 4.3 이하, Opera Mobile 10 이하 등)들을 위해 CSS2에서 폰트로 활용할 수 있도록 명시 된 SVG(Scalable Vector Graphics) 포맷을 이용하기도 합니다.
SVG 포맷의 서체는 하나의 파일 안에 여러 서체를 넣고 ID(ex. #NanumGothicRegular)를 부여하여 개별적으로 호출 할 수 있고, SVG Viewer가 탑재된 모든 기기에서 표현 할 수 있는 장점이 있지만, 서체에 대한 폰트 힌팅 정보가 없기 때문에 작은 글씨를 표현할 때 가독성이 떨어지는 단점도 있습니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot); /* IE 호환성 보기 */
src: url(NanumSquareR.eot#iefix) format('embedded-opentype'), /* IE 6 ~ 8 */
url(NanumSquareR.woff) format('woff'), /* 모던 브라우저 */
url(NanumSquareR.ttf) format('truetype'),
url(NanumSquareR.svg#NanumSquareR) format('svg'); /* 구 모바일 브라우저 */
}
힌팅이란?
윤관선 글자 정보에 약간의 힌트(hint)를 주어 폰트를 비트맵으로 변환할 때 그 힌트를 이용하여 글자의 변형이나 왜곡 없이 더 나은 출력 결과를 얻게 만든다는 의미에서 붙여진 용어 입니다. 즉, 모니터상에서 글씨가 보다 뚜렷하게 보이게끔 글자 스스로 약간 글모양을 변형시키는 기술 입니다.
첫번째 줄 ‘활’은 힌팅이 적용되지 않은 폰트인데 확대했을 때 깨져 보이는 부분이 있지만 두번째 줄 ‘활’은 힌팅이 적용되어있고 확대 했을 때 깨짐이 덜합니다.
3-4. WOFF2 지원 브라우저
WOFF1 버전에 비해 평균 30%정도 압축 형식을 제공(경우에 따라 최대 50%)하는 WOFF2를 추가합니다.
@font-face {
font-family: NanumSquareWeb;
src: url(NanumSquareR.eot); /* IE 호환성 보기 */
src: url(NanumSquareR.eot#iefix) format('embedded-opentype'), /* IE 6 ~ 8 */
url(NanumSquareR.woff2) format('woff2'), /* WOFF2 지원 브라우저 */
url(NanumSquareR.woff) format('woff'), /* 모던 브라우저 */
url(NanumSquareR.ttf) format('truetype'),
url(NanumSquareR.svg#NanumSquareR) format('svg'); /* 구 모바일 브라우저 */
}
3-5. 정리
현재 뮤직 서비스에서 사용하고 있는 코드 입니다.(구버전 모바일 브라우저 대응을 위한 SVG는 삭제되었습니다)
@font-face {
font-family: NanumSquare;
src: url(NanumSquareR.eot); /* IE 호환성 보기 */
src: url(NanumSquareR.eot#iefix) format('embedded-opentype'), /* IE 6 ~ 8 */
url(NanumSquareR.woff2) format('woff2'), /* WOFF2 지원 브라우저 */
url(NanumSquareR.woff) format('woff'), /* 모던 브라우저 */
url(NanumSquareR.ttf) format('truetype');
}
위의 코드를 가지고 브라우저별로 접속했을 때 어떤 폰트가 다운로드 되는지 알아보겠습니다.
- IE 6~8 로 접근하면 NanumSquareR.eot? 가 다운로드 됩니다.
- IE 호환성 보기 로 접근하면 NanumSquareR.eot 가 다운로드 됩니다.
- IE 9이상 으로 접근하면 NanumSquareR.eot? 가 다운로드 됩니다.
- 만약 url(../webfont/NanumSquare/NanumSquareR.eot?#iefix) format(’embedded-opentype’) 부분을 local(“☺”) 로 바꾸면 NanumSquareR.woff가 다운로드 됩니다.
- Safari 로 접근할 때는 NanumSquareR.woff가 다운로드 됩니다.
- Chrome, firefox, opera 로 접근할 때는 NanumSquareR.woff2가 다운로드 됩니다.
아래의 코드는 모든 브라우저를 대응하고 IE에서 eot 파일이 아닌 woff 파일을 로드받을 수 있게 하는 코드입니다.
@font-face {
font-family: NanumSquare;
src: url(NanumSquareR.eot); /* IE 6 ~ 8, IE 호환성 보기 */
src: local(☺),
url(NanumSquareR.woff2) format('woff2'), /* IE Edge, WOFF2 지원 브라우저 */
url(NanumSquareR.woff) format('woff'), /* IE 9+, 모던 브라우저 */
url(NanumSquareR.ttf) format('truetype');
}
4. 웹폰트를 파일 관리 방법
4-1. 서버에 직접 업로드 하는 경우
<!-- 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;
}
서버에 직접 업로드하는 경우는 css에 @font-face를 직접 선언해 주어야 합니다. 폰트의 종류가 많을 수록 @font-face를 많이 선언해야 해서 복잡하지만 기준브라우저에 따라 코드를 추가, 삭제 할 수 있습니다. 그리고 다른 CDN을 이용하는 것 보다 속도가 빠르고 안전합니다.
4-2. 구글 CDN을 이용하는 경우
<!-- 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;
}
구글 CDN을 이용하면 별도의 @font-face를 정의하지 않아도 되기 때문에 편리하지만 서버에 직접 업로드하는 것보다 속도가 느리고 구글 CDN 서버가 제대로 동작하지 않을 때는 웹폰트를 제공받지 못 할 수 있습니다. 구글 CDN의 경우 @font-face에 WOFF와 WOFF2만 지원하므로 IE 6~8, IE 호환성 보기 모드에서는 웹폰트를 사용할 수 없습니다.
그래서 서버가 있으면 직접 서버에 업로드하여 사용하는 것이 좋습니다.
4-3. 로컬 서버 vs 구글 웹폰트 로드 차이
예상했던 대로 로컬서버에서 파일을 로드하는게 더 빠릅니다.
로컬서버에서 불러올 때:
구글에서 불러올 때:
하지만 티스토리와 같이 폰트를 서버에서 올릴 수 없을 경우 구글 웹폰트를 로드해서 사용할 수 있습니다.
5. 웹폰트를 사용하지 않는 이유
웹폰트를 사용하지 않는 이유는 두 가지가 있습니다. 첫번째는 IE 브라우저에서 폰트 로드가 완료되면 깜빡거리는 현상인 FOUT 때문이고 두번째는 웹폰트 용량에 따른 성능 문제입니다.
FOUT현상과 함께 IE 외 다른 브라우저(Chrome, Safari 등)에서 나타나는 현상인 FOIT, 스크립트로 임의로 만든 FOFT 현상을 같이 알아보고 FOUT현상을 다른 현상으로 바꾸는 방법을 알아보겠습니다.
5-1. FOUT / FOIT / FOFT
5-1-1. FOUT(Flash of Unstyled Text)
FOUT란? 웹 폰트 파일이 로드되기 전 까지 기본서체가 노출되다가 웹 폰트 로드가 완료되면 웹폰트로 바뀌면서 깜빡이는 현상 입니다. FOUC(Flash of Unstyled Content)라고 불리기도 합니다. IE 브라우저에서 발생합니다.
5-1-2. FOIT(Flash of Invisible Text)
FOIT란? 웹 폰트 파일이 로드되기 전 까지 웹 페이지를 로드하지 않고 웹폰트 로드가 완료되면 웹 페이지를 로드하기 때문에 로드가 완료되기 전 까지 텍스트가 안보이는 현상 입니다. IE 브라우저를 제외한 나머지 브라우저(Chrome, Safari 등)에서 발생합니다.
5-1-3. FOFT(Flash of Faux Text)
FOFT란? 웹 폰트 파일에 font-weight, font-style과 관련된 서체가 있을 시 로드 전 브라우저에서 임의로 서체의 굵기와 스타일을 생성하여 노출하고 웹폰트 로드가 완료되면 웹 폰트로 바뀌는 현상입니다. 이는 스크립트로 만들어진 현상으로 시스템글꼴 → 웹 폰트 Regular → 웹 폰트 Bold 순으로 바뀝니다.
언뜻보면 화면이 두번 깜빡이기 때문에 FOUT보다 안 좋아 보입니다. 그런데 왜 FOFT라는 현상을 스크립트로 만들었을까요? 그 이유는 웹 폰트의 종류가 많을 경우 첫 폰트를 빠르게 보여주기 위해서 입니다.
FOUT와 FOIT는 나눔스퀘어 Regular와 나눔스퀘어 Bold 웹 폰트를 사용할 때 두 웹 폰트를 동시에 다운로드 하게 됩니다. 두 폰트가 동시에 다운로드 되기 때문에 다운로드가 완료되어 웹 폰트 적용 시점은 30초 이후입니다.
하지만 FOFT는 나눔스퀘어 Regular와 나눔스퀘어 Bold 웹 폰트를 사용할 때 나눔스퀘어 Regular 먼저 다운로드 하고 나눔스퀘어 Bold를 다운로드 합니다. 그래서 나눔스퀘어가 Regular가 23초 쯤에 다운로드가 완료되어 먼저 적용되고 나눔스퀘어 Bold는 30초 이후에 적용됩니다.
5-1-4. Google Webfont Loader
구글에서 제공하는 Google Webfont Loader를 사용하면 위 3가지 현상을 자유롭게 바꿀 수 있습니다.
https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js
WebFont.load({
custom: {
families: ['NanumSquare'], // @font-face에 선언한 폰트 패밀리명
urls: ['../css/NanumSquare.css'], // @font-face가 선언된 css 경로
}
});
위의 스크립트를 적용하면 해당 웹 폰트를 추적하면서 자동으로 html
에 아래의 클래스가 적용됩니다.
폰트패밀리는 @font-face에서 선언한 폰트 패밀리명이고 스타일 굵기는 알파벳 n에 @font-face에서 선언한 font-weight
의 백의자리 수를 합친 값 입니다.
- wf-loading: 1개 이상 폰트가 로딩 중
- wf-active: 1개 이상 폰트 사용 가능
- wf-inactive: 모든 폰트 사용 불가능
- wf-폰트패밀리-스타일굵기-loading: 특정 폰트 로딩 중
- wf-폰트패밀리-스타일굵기-active: 특정 폰트 사용 가능
- wf-폰트패밀리-스타일굵기-inactive: 특정 폰트 사용 불가능
예를 들어, 나눔스퀘어 Regular와 나눔스퀘어 Bold 웹 폰트를 Google Webfont Loader를 통해 적용했다고 하면 wf-active wf-nanumsquare-n4-active wf-nanumsquare-n7-active
클래스가 html
에 추가 될 것 입니다.
위의 클래스를 이용하여 FOUT, FOIT, FOFT 현상을 만들어보겠습니다.
FOUT
<style>
.wf-nanumsquare-n4-active #fonts_loaded { /* 웹 폰트 사용 가능할 때 속성 적용 */
font-family: NanumSquare, sans-serif;
}
</style>
FOIT
<style>
.#fonts-loaded { /* 웹 폰트 다운로드 전에는 화면을 보여주지 않음 */
display: none;
}
.wf-nanumsquare-n4-active #fonts_loaded { /* 웹 폰트 사용이 가능하면 화면을 보여주고 웹 폰트 속성 적용 */
display: block;
font-family: NanumSquare, sans-serif;
}
</style>
FOFT
<style>
.wf-nanumsquareregular-n4-active #fonts_loaded { /* 나눔스퀘어 Regular 폰트가 사용 가능할 때 웹 폰트 속성 적용 */
font-family: NanumSquare-Regular, sans-serif;
}
.wf-nanumsquarebold-n4-active #fonts_loaded { /* 나눔스퀘어 Bold 폰트가 사용 가능할 때 웹 폰트 속성 적용 */
font-family: NanumSquare-Bold, sans-serif;
}
</style>
// 스크립트
WebFont.load({
custom: {
families: ['NanumSquare-Regular', 'NanumSquare-Bold'],
urls: ['../css/NanumSquare.css']
}
})
5-2. 성능
실제로 이미지 폰트를 많이 사용하지 않는 경우에는 웹 폰트를 사용하는 것보다 이미지 폰트를 사용하는 것이 좋습니다.
- 이미지폰트 적용 페이지: 이미지 용량 136KB
- 웹폰트 적용 페이지: 웹폰트 용량 273KB
웹 폰트를 적용했을 때 137KB정도 용량이 더 크지만, 웹 폰트, 이미지 폰트 모두 사이트에 한 번 접속하면 캐시에 저장되고 이후에 접속할 때 마다 캐시에서 불러와 사용합니다. 그러므로 이미지폰트를 여러 페이지에 사용할 경우 이미지 폰트보다 웹 폰트를 사용하는 것이 효율적입니다.
예를 들어 아래 동선과 같이 여러 페이지를 이동한다고 가정했을 때를 비교해보겠습니다.
뮤직홈 → 이용권 구매 → 알뜰 이용권 자세히 보기
웹 폰트 적용환경 사용자A는 뮤직홈에 처음 접속했을 때 웹폰트가 다운받아지고 캐시에 저장됩니다. 이 후 이용권 구매, 알뜰 이용권 자세히 보기 페이지에서는 캐시에 저장된 웹폰트를 불러 사용합니다.
이미지 폰트 적용환경 사용자B는 뮤직홈, 이용권 구매, 알뜰 이용권 자세히 보기 에서 이미지파일 136KB를 받기 때문에 총 408KB를 다운받게 됩니다.
이미지 폰트도 캐시를 이용하지만 각 페이지에서 사용한 이미지가 모두 다른 파일이기 때문입니다.(모두 같은 이미지 파일에 저장하게되면 이미지 용량이 너무 커지게 됩니다.)
6. 웹폰트를 빠르게 로드하는 방법
6-1. data-uri
폰트도 이미지 처럼 URI로 표현할 수 있습니다. 윈도우 사용자 분들은 Webfont Generator, MAC OS 사용자 분들은 터미널에서 base64 폰트.woff -b 0 > 폰트.base64.txt
명령어를 통해 쉽게 만들 수 있습니다.
6-1-1. 사용방법
사용 방법은 url에 폰트의 경로 대신에 uri값만 넣어주면 됩니다.
@font-face {
font-family: NanumSquare;
src: url(data:application/font-woff;base64,d09GRgABAAAAADEFFFFFEDCrgAAA...);
}
6-1-2. 장·단점
장점
- FOUT 현상이 발생하지 않습니다.
- 외부 데이터를 별도의 파일로 두지 않고 하나의 HTML 파일로 관리할 수 있습니다.
- 파일이 하나이다보니 HTTP 헤더정보나 TCP 패킷 크기가 맞지 않아서 발생하는 오버헤드가 발생하지 않습니다.
- 용량이 작을 때 리퀘스트 수를 줄여서 빠르게 전송할 수 있습니다.
단점
- 캐싱을 하지 않아 별도의 캐싱 정책을 주어야 합니다.
- IE7 이하에서는 data-uri를 지원하지 않고 IE8 이하에서는 어느정도 크기 이상이면 로드하지 못합니다.
- 큰 데이터를 data-uri로 사용하면 오히려 더 느려집니다.
6-1-3. data-uri vs url
웹 폰트를 uri 값으로 적용했을 때와 url로 적용했을 때 파일크기와 다운로드 완료 시간을 비교 해 보았습니다.
(Droid Sans는 영문 폰트, 나눔스퀘어는 한글 2,350자, 나눔바른고딕은 한글 11,172자, 본고딕은 모든 한글이 다 들어있는 폰트입니다.)
파일크기는 영문, 한글 폰트 모두 url로 적용했을 경우 더 작았고 다운로드 완료 시간은 영문 폰트일 경우에는 uri가 빨랐고 한글 폰트일 경우 url이 더 빨랐습니다. 웹 폰트로 영문 폰트를 사용할 경우에는 uri로 적용해 보는 것도 좋을 것 같습니다.
6-2. preload
브라우저에게 리소스가 필요할 것이라고 알려주는 힌트입니다. 하지만 리소스를 로드하는것이 좋을지 안 좋을지는 브라우저가 결정합니다.
6-2-1. 사용방법
<head>
<link rel="preload" href="../webfont/NanumSquare/NanumSquare.woff" as="font" crossorigin>
</head>
속성중에서 as와 crossorigin이 있는데 preload를 사용할 경우에는 반드시 사용해 주어야 합니다. 만약 사용하지 않으면 같은 파일을 두번 요청하게 됩니다.
* prefetch와 preload는 다른 속성입니다. preload는 현재 페이지에서 사용되어질 가능성이 높은 리소스(웹 폰트, 주요 이미지)를 필요로 할 때 사용하고 prefetch는 향후 이동에서 사용할 리소스(css)를 필요로 할 때 사용합니다. 그러므로 웹 폰트를 사용할 때에는 preload를 사용하셔야 합니다.
6-2-2. 지원범위
Chrome, Opera, Android에서만 사용할 수 있습니다.
6-3. 서브셋
원하는 문자만 사용해서 폰트 크기를 줄이는 방법 입니다. 왼쪽은 한글 11,172자인 나눔바른고딕이고 오른쪽은 서브셋을 통해 한글 2,350자로 줄인 나눔바른고딕입니다. 갃, 갅, 갆 등과 같은 문자는 사용할 수 없지만 용량이 약 2MB 정도 줄었습니다.
6-3-1. 사용방법
서브셋 폰트 메이커를 이용하여 쉽게 만들 수 있습니다.
- PC에서 폰트 파일을 선택합니다.
- 서브셋이 완료된 폰트를 저장할 경로를 선택합니다.
- 사용 할 문자를 적습니다.
- 폰트패밀리명을 적습니다.
- WOFF 컨버터를 실행할지 선택합니다. WOFF 컨버터를 실행하지 않으려면 체크를 해제해도 됩니다.
- 변환합니다.
7. 구글 웹폰트를 빠르게 로드하는 팁
HEAD 파일에서 CSS보다 더 빠르게 로드 해야 합니다.
참조링크를 사용합니다.
– 가져다 사용하는 경우는 css내에서 @import방법, 참조링크를 사용하는 방법, 자바스크립트를 이용하는방법 3가지가 있는데 참조링크를 이용하면 HTML의 최상위에 코드를 넣을 수 있으며, CSS 파일보다 더 빠르게 로드될 수 있습니다. @import 코드는 CSS 파일안에 넣어야 하는데 이는 스타일 되지 않은 텍스트가 번쩍거리는 현상을 일으킬 수 있습니다.(flash of unstyled text:FOUT)
적은 폰트를 로드 해야 합니다.
표제를 위한 볼드타입과 기사를 위한 가독성이 좋은 폰트(최대 2개의 폰트)를 선정하는 것이 좋습니다.
– 폰트는 많을 수록 로딩 시간이 더 길어집니다.
폰트 로드 코드를 결합해서 사용합니다.
– 코드 한 줄에 여러 구글 폰트를 로드할 수 있습니다. 로드하려는 각 폰트마다 한 줄 코드를 넣을 필요가 없습니다. Open Sans와 Oswald 폰트를 사용하고 싶으면 아래 처럼 한 줄에 적으면 좋습니다.
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Oswald">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans|Oswald">
폰트의 기본 옵션을 로드하는 것이 좋습니다.
한 가지 옵션만 선택했을 때:
많은 옵션을 선택했을 때:
구글에서 제공하는 Google Webfont Loader를 사용합니다.
8. 참고문서
- MDN @font-face: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face
- W3C @font-face: https://www.w3.org/TR/css-fonts-3/#font-face-rule
- Bulletproof의 @font-face 문법 : https://www.paulirish.com/2009/bulletproof-font-face-implementation-syntax/
- 웹 폰트 속성 설명: http://naradesign.net/wp/2012/06/19/1830
- Using @font-face: https://css-tricks.com/snippets/css/using-font-face/
- Beautiful CSS 웹폰트 파헤치기: http://www.beautifulcss.com/archives/431
- The @font-face Rule And Useful Web Font Tricks: https://www.smashingmagazine.com/2011/03/the-font-face-rule-revisited-and-useful-tricks/
- 구글 웹폰트 빠르게 로드하는 팁: https://nolboo.kim/blog/2013/10/22/google-web-font-faster-tip/
- [웹폰트]올바른 방법으로 로딩하자: http://web-atelier.tistory.com/43
- 비동기 웹폰트 로딩: https://calendar.perfplanet.com/2016/loading-web-fonts-asynchronously/
- fontfaceobserver: https://fontfaceobserver.com/
- 올바르게 웹폰트 로딩하기: http://hackya.com/kr/%EC%98%AC%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%9B%B9%ED%8F%B0%ED%8A%B8-%EB%A1%9C%EB%94%A9%ED%95%98%EA%B8%B0/
- Web Font Loader: https://github.com/typekit/webfontloader
- data-uri로 웹폰트 사용하기: https://blog.outsider.ne.kr/1138
- Webfont Data-uri: https://www.zachleat.com/web/web-font-data-uris/
- W3C preload: https://www.w3.org/TR/preload/
- preload, prefetch: https://www.bramstein.com/writing/preload-hints-for-web-fonts.html
- 웹 폰트 성능: https://speakerdeck.com/bramstein/web-fonts-performance
- 웹 폰트를 로컬스토리지에 저장하는 방법(캐시 안전성 증가, 깜빡임 제거): http://mytory.net/2016/06/15/webfont-best-practice.html
- CSS3 property font-size-adjust: http://webdesignernotebook.com/css/the-little-known-font-size-adjust-css3-property/
- MDN font-display: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-display
18개의 댓글
김수린 · 2017년 5월 19일 11:06 오전
좋은 글 감사합니다!
정독하면서 읽었습니다!
Jae Won Jang · 2017년 6월 20일 9:18 오전
이만큼 잘 정리된 웹폰트 가이드는 본적이 없네요.
최고입니다!
youngmin kim · 2017년 7월 5일 12:24 오후
최고의 웹폰트 가이드입니다!
Happist · 2017년 10월 7일 8:43 오후
폰트 적용 방법을 찾아 인터넷을 뒤지다가 멋진 글을 발견했네요.
비록 제가 원하는 방식은 아니지만 웹폰트 관련 과히 집대성했다고할만합니다.
잘 보고 갑니다.
Sol Amy Lee · 2017년 10월 25일 9:09 오후
엄청난 가이드네요! 많은 도움이 되었습니다. 감사합니다.
제 웹페이지 (solsol.io)에 @import 로 불러오니 로딩이 느려 로컬로 불러오되
Foit 현상이 고민이었는데… 어떻게 적용해야할지 해법을 얻었습니다!!
곽석종 · 2017년 11월 30일 2:01 오후
웹폰트 lazy loading 관련하여 http://keithclark.co.uk/articles/loading-css-without-blocking-render/ 참고하시면 좋습니다.
Moon · 2018년 2월 2일 9:01 오후
어마어마한 정리입니다. 한참 보고 공부하고 갑니다.
Junhui Park · 2018년 2월 12일 10:01 오전
엄청납니다 정말 감사합니다!
Amerimnos · 2018년 2월 24일 8:59 오전
엄청나네요. 덕분에 궁금증이 거의 불렸습니다!
Jin-Woo Jung · 2018년 3월 2일 6:05 오전
정말..대단하십니다. 너무 감사하고 ^-^ 잘 참고하겠습니다.
김미진 · 2020년 8월 14일 1:49 오후
자료 정말 감사드립니다. 웹폰트에 관해선 정말 완벽 최고입니다.
jaime · 2020년 8월 29일 10:23 오후
잘 읽었습니다. 폰트에 대한 글을 정리 중인데 본문 글을 많이 참고해서 작성했는데 출처를 남기고 사용해도 될까요? 불편하시면 삭제하도록 하겠습니다.
WIT Manager · 2020년 9월 7일 5:01 오후
답변이 늦었습니다. 출처 및 차용 범위를 본문에 기록해주시면 활용 가능하십니다.
와니 · 2020년 9월 8일 5:35 오후
와 이 글 하나면 웹폰트 정복이네요! 진짜 도움 많이 되었습니다. 감사합니다!
서현오 · 2021년 10월 2일 2:49 오후
진짜 컨텐츠 지리네요
궁금합니다 · 2023년 10월 18일 10:45 오전
link로 가져오는것보다 font-face가 안전하다는것일까요 ? + 더 빠르다는 것일까요??
문의 · 2023년 12월 13일 1:57 오후
안녕하세요, 웹폰트 포스팅 관련 문의드리고 싶은 것이 있습니다. hyelim@sandoll.co.kr 으로 메일 보내주실 수 있을까요? 상세 내용 메일로 전달드리겠습니다.
웹폰트 파헤치기 – W · 2018년 6월 28일 1:49 오후
[…] http://wit.nts-corp.com/2017/02/13/4258 […]