Browser - Font Rendering
◆웹 브라우저는 폰트를 어떻게 렌더링할까?
웹 페이지를 처음 접속했을 때 기본 폰트가 잠깐 보였다가 몇 초 후 웹폰트(Web Font)로 변경되는 현상을 본 적이 있을 것이다.
왜 이런 현상이 발생하는 걸까?
이를 이해하기 위해서는 브라우저가 웹폰트를 로드하고 렌더링하는 과정을 알아야 한다.
◆전체 렌더링 과정
사용자 접속
│
▼
HTML 다운로드
│
▼
CSS 다운로드
│
▼
CSS 파싱
│
▼
@font-face 발견
│
▼
브라우저 캐시(Cache) 확인
│
├── 캐시에 있음
│ │
│ ▼
│ 폰트 즉시 사용
│
└── 캐시에 없음
│
▼
폰트 다운로드
│
▼
폰트 메모리 로드
│
▼
Unicode → Glyph 매핑
│
▼
Text Shaping(문자 조합)
│
▼
Layout 계산
│
▼
화면(Rendering)
1. HTML 다운로드
사용자가 웹 사이트에 접속하면 브라우저는 가장 먼저 HTML 문서를 요청한다.
GET /index.html
예를 들어 다음과 같은 HTML이 있다고 가정해 보자.
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<p>Hello World</p>
</body>
브라우저는 HTML을 위에서 아래로 읽다가 CSS 파일이 필요하다는 것을 인식한다.
2. CSS 다운로드 및 파싱
브라우저는 CSS 파일을 요청한다.
GET /style.css
CSS를 읽는 도중 다음과 같은 코드를 발견한다.
@font-face {
font-family: "Noto Sans";
src: url("./fonts/NotoSans-Regular.woff2") format("woff2");
}
body {
font-family: "Noto Sans";
}
이 순간 브라우저는
“이 페이지를 그리기 위해서는 NotoSans-Regular.woff2 파일이 필요하구나.”
라고 판단한다.
VS Code에서 HTML 파일을 브라우저로 실행하더라도 프로젝트 폴더 안의 모든 폰트 파일을 다운로드하는 것은 아니다. 브라우저는
@font-face의src에 작성된 순서대로 지원 여부를 확인한 뒤, 지원 가능한 첫 번째 포맷 하나만 다운로드한다.나머지 포맷은 다운로드하지 않는다.
3. 브라우저 캐시(Cache) 확인
브라우저는 폰트를 바로 다운로드하지 않는다.
먼저 자신의 캐시에 이미 해당 폰트가 저장되어 있는지 확인한다.
NotoSans-Regular.woff2
│
▼
브라우저 캐시에 존재하는가?
├── YES → 바로 사용
└── NO → 서버에서 다운로드
캐시(Cache)란?
캐시는 브라우저가 이전에 다운로드한 리소스를 임시로 저장해 두는 공간이다.
대표적으로 다음과 같은 파일들이 저장된다.
- HTML
- CSS
- JavaScript
- 이미지
- 폰트(Web Font)
즉, 한번 다운로드한 웹폰트는 다음 방문 시 다시 다운로드하지 않고 캐시에 저장된 파일을 바로 사용할 수 있다.
[캐시를 사용한 경우] from memory cache

[캐시를 사용하지 않은 경우] from disk cache

4. 폰트 다운로드
캐시에 폰트가 없다면 서버에 요청한다.
GET /fonts/NotoSans-Regular.woff2
다운로드가 완료되면 브라우저는 해당 폰트를 메모리에 로드한다.
5. Unicode와 Glyph 매핑
브라우저는 화면에 출력할 문자열을 Unicode 코드 포인트 형태로 가지고 있다.
예를 들어
안녕하세요
는 내부적으로
U+C548
U+B155
U+D558
...
와 같이 저장되어 있다.
폰트 파일 안에는 각각의 Unicode에 대응하는 Glyph(글리프)가 저장되어 있다.
Unicode
│
▼
U+C548
│
▼
'안' 글자 모양(Glyph)
브라우저는 Unicode를 이용하여 해당 글자의 Glyph를 찾아낸다.
6. Text Shaping (문자 조합)
영문은 대부분 문자 하나가 글자 하나를 의미한다.
예를 들어
CAT
은
C
A
T
각 문자를 그대로 그리면 된다.
하지만 힌디어, 벵골어, 판자브어, 태국어와 같은 언어는 그렇지 않다.
예를 들어 판자브어
ਕੀ
는 실제로는
ਕ
ੀ
두 개의 Unicode 문자로 이루어져 있다.
하지만 브라우저는 이를 따로 그리지 않는다.
ਕ + ੀ
│
▼
하나의 글자처럼 조합
이 과정을 Text Shaping이라고 한다.
Text Shaping 과정에서는 다음과 같은 작업이 함께 수행된다.
- Combining Mark(결합 문자)
- Ligature(합자)
- 문자 위치 조정(Positioning)
- 언어별 OpenType 규칙 적용
이 과정을 거쳐 다양한 언어가 자연스럽게 표시된다.
7. Layout 계산
이제 브라우저는 글자를 어디에 배치할지 계산한다.
예를 들어
font-size:16px;
line-height:24px;
font-weight:700;
letter-spacing:1px;
와 같은 스타일을 기반으로
- 글자의 위치
- 줄 간격(Line Height)
- 자간(Letter Spacing)
- 굵기(Font Weight)
등을 계산한다.
8. 화면(Rendering)
마지막으로 브라우저는 계산된 결과를 GPU 또는 CPU를 이용하여 화면에 그린다.
최종적으로 사용자는
Hello
안녕하세요
ਸਤ ਸ੍ਰੀ ਅਕਾਲ
과 같은 결과를 보게 된다.
◆왜 처음에는 기본 폰트가 보일까?
웹폰트는 다운로드가 완료되어야 사용할 수 있다.
예를 들어
0ms HTML 다운로드 완료
50ms CSS 다운로드 완료
80ms 웹폰트 요청
500ms 웹폰트 다운로드 완료
550ms 웹폰트 적용
웹폰트가 다운로드되는 동안 브라우저는 임시로 시스템 기본 폰트를 사용한다.
기본 폰트 표시
│
▼
웹폰트 다운로드 완료
│
▼
웹폰트 적용
그래서 사용자는
처음에는 기본 폰트가 보였다가 잠시 후 웹폰트로 변경되는 현상
을 보게 된다.
이 현상을 FOUT(Flash of Unstyled Text) 라고 한다.
반대로 웹폰트가 모두 다운로드될 때까지 텍스트 자체를 숨기는 방식을 FOIT(Flash of Invisible Text) 라고 한다.
◆브라우저 캐시가 중요한 이유
브라우저는 한번 다운로드한 웹폰트를 캐시에 저장한다.
다음 방문 시에는
캐시 확인
│
▼
폰트 존재
│
▼
즉시 사용
하므로 다시 다운로드할 필요가 없다.
그 결과
- 페이지 로딩 속도가 빨라진다.
- 네트워크 사용량이 줄어든다.
- 웹폰트가 거의 즉시 적용된다.
◆정리
웹폰트는 단순히 글자 모양만 저장한 파일이 아니다.
브라우저는 웹폰트를 다운로드한 뒤 다음 과정을 거쳐 화면을 완성한다.
- HTML 다운로드
- CSS 다운로드 및 파싱
@font-face발견- 브라우저 캐시 확인
- 필요 시 웹폰트 다운로드
- Unicode와 Glyph 매핑
- Text Shaping을 통한 문자 조합
- Layout 계산
- 화면 렌더링(Rendering)
댓글남기기