AI VIDEO BRIEFING
폰트 파일 내부 구조 완전 해부: 글리프와 셰이핑, 힌팅과 가변 폰트가 웹 성능에 미치는 영향
같은 16픽셀인데 왜 글자 크기가 달라 보일까. 폰트 파일 안에 든 다섯 가지 요소부터 셰이핑과 래스터화, CPU에서 실행되는 힌팅 바이트코드, 가변 폰트, 레이아웃 이동과 서브셋까지 렌더링 전 과정을 풀어낸다.

핵심 메시지
쉽게 이해하기
영상은 세 가지 수수께끼로 시작한다. 같은 브라우저에서 font-size를 16픽셀로 똑같이 지정했는데 두 글자의 크기가 달라 보이고, office라는 여섯 글자를 썼는데 실제로는 네 개의 모양만 그려지며, 12픽셀에서 2,000픽셀까지 키워도 글자는 늘 선명하다. 답은 모두 확장자가 .ttf나 .woff2인 파일 안에 있다.
폰트 파일은 크게 다섯 부분으로 나뉜다. 글자 모양은 픽셀 이미지가 아니라 베지에 곡선으로 된 벡터 윤곽선이며, 트루타입은 2차 베지에를, 오픈타입은 3차까지 쓴다. 파일이 담고 있는 것은 완성된 'A'가 아니라 'A'를 그리는 방법이므로 어떤 크기로도 선명하게 렌더링된다. 문자 코드와 글리프를 잇는 표는 cmap이고, 여기에 항목이 없는 문자는 브라우저가 다른 폰트에서 빌려오기 때문에 문장 속 한 글자만 어색해 보이는 일이 생긴다. 나머지는 자간을 다듬는 커닝 규칙과 힌팅이다.
글자가 화면에 나오기까지는 세 단계를 거친다. 셰이핑은 입력한 문자열을 그릴 글리프 순서로 바꾸는 과정인데, ffi가 하나의 합자로 그려지거나 아랍 문자처럼 단어 내 위치에 따라 최대 네 가지 모양이 되는 경우가 있어 크롬·파이어폭스·엣지는 HarfBuzz에, 사파리는 애플의 Core Text에 이 작업을 맡긴다. 이어 래스터화가 벡터를 픽셀로 옮기고, 대각선에서 생기는 계단 현상은 가장자리 픽셀을 회색조로 칠하는 안티에일리어싱으로 완화한다.
가장 낯선 것은 힌팅이다. 설정 파일이나 값 목록이 아니라, 새로운 크기로 렌더링될 때마다 CPU에서 실행되는 바이트코드다. 트루타입은 전용 가상 머신을 갖고 있고 이 실행기는 리눅스와 안드로이드의 FreeType, 윈도의 DirectWrite, 애플의 Core Text에 들어 있다. 프로그램이 하는 일은 '이 크기에서는 이 세로획을 픽셀 경계에 맞춰라' 같은 지시를 래스터라이저에 전달하는 것이다. 고해상도 화면에서는 픽셀 격자가 촘촘해 효과가 잘 드러나지 않지만, 일반 모니터에서 우리가 읽어온 본문 글자는 대부분 이 작은 프로그램의 출력물이다.
실무에서 바로 쓸 만한 대목은 뒤쪽에 있다. 가변 폰트는 굵기 같은 축에 연속 범위를 정의하고 양 끝의 제어점을 보간하므로, CSS의 font-weight에 437 같은 값을 넣어도 의미 있는 결과가 나온다. 폰트가 늦게 로드되어 대체 폰트에서 교체될 때 생기는 레이아웃 이동은 검색 순위에 반영되는 지표까지 건드리는데, @font-face의 size-adjust와 ascent-override, descent-override로 대체 폰트의 메트릭을 맞춰주면 교체가 눈에 띄지 않는다. 마지막으로 한중일 글리프를 모두 담은 폰트는 수십 메가바이트에 이르므로, 쓰지 않는 글리프를 걷어내는 서브셋이 가장 손쉬운 성능 개선책으로 제시된다.
주요 인사이트
- 폰트가 크기와 무관하게 선명한 이유는 해상도가 높아서가 아니라, 파일이 결과물이 아니라 생성 방법을 저장하기 때문이다. 같은 원리로 힌팅 역시 값이 아닌 실행 코드로 저장되어 크기마다 다른 판단을 내릴 수 있다.
- font-size가 글자 높이를 정하지 않는다는 사실은 디자인 시스템에서 폰트를 교체할 때마다 시각적 크기가 흔들리는 이유를 설명해 준다. 결정권은 CSS가 아니라 폰트 내부의 메트릭에 있다.
- 레이아웃 이동은 미관 문제로 여겨지기 쉽지만, 영상은 이것이 Core Web Vitals 점수를 통해 검색 노출과 트래픽에 직결된다고 짚는다. 해결책인 메트릭 오버라이드는 대부분의 최신 브라우저가 지원하는데도 거의 쓰이지 않는다.
- 구글 폰트는 유니코드 범위별로 파일을 미리 쪼개 제공해 브라우저가 필요한 조각만 받게 한다. 직접 호스팅하는 경우에도 pyftsubset 같은 도구로 같은 효과를 낼 수 있고, 영어 서브셋은 원본보다 한두 자릿수 작아진다.
자주 묻는 질문
같은 font-size인데 폰트마다 크기가 달라 보이는 이유는 무엇인가요?
font-size는 글자의 높이가 아니라 글자가 놓이는 보이지 않는 설계 격자의 높이를 정하기 때문입니다. 기준선의 위치, 소문자의 높이, 아래로 내려가는 획의 깊이는 모두 폰트 내부에서 정해지므로 같은 값이라도 시각적 크기가 달라집니다.
힌팅은 정확히 무엇인가요?
폰트 안에 들어 있는 바이트코드 프로그램입니다. 새로운 크기로 래스터화될 때마다 CPU에서 실행되어 '이 크기에서는 이 획을 픽셀 경계에 맞추라'거나 '이 곡선을 두껍게 하라' 같은 지시를 렌더러에 전달합니다. 트루타입은 이를 위한 가상 머신을 운영체제의 폰트 렌더링 라이브러리에 두고 있습니다.
가변 폰트를 쓰면 용량이 줄어드나요?
굵기를 세 종류 이상 쓴다면 대개 그렇습니다. 가변 폰트는 축의 양 끝에 해당하는 제어점 집합을 담고 브라우저가 그 사이를 보간하므로, 굵기마다 파일을 따로 받는 방식보다 전체 전송량이 작아지는 경우가 많습니다.
폰트 때문에 생기는 레이아웃 이동은 어떻게 막나요?
@font-face에 size-adjust, ascent-override, descent-override 세 가지 설명자를 써서 대체 폰트의 메트릭을 본 폰트에 맞추면 됩니다. 메트릭이 일치하면 폰트가 교체되어도 줄 높이가 변하지 않아 레이아웃이 밀리지 않습니다.
원문과 출처
이 글은 원본 영상의 자막을 바탕으로 한국어 독자를 위해 요약했습니다. 전체 맥락과 최신 정보는 원문에서 확인하세요.
YouTube 원본 영상 보기 ↗