04 — Variable Fonts
정적 폰트 9개를 보내는 대신, 가변 축을 가진 폰트 1개를 보낸다. Variable font는 디자인 공간을 코드로 보간하는 폰트 기술이다.
한 문장 답 (Pyramid Top)
Variable font는 하나의 폰트 파일이 N차원 축을 가지고, CSS가
font-variation-settings로 그 축의 임의 위치를 지정하면 폰트 엔진이 실시간으로 보간해 글자를 그리는 기술이다. 정적 폰트 9개 (Thin..Black) = 약 250KB × 9 = 2.25MB, Variable 폰트 1개 = 약 350KB — 거의 6.4배 압축되면서도 200, 250, 333 같은 비표준 weight까지 표현 가능하다.
Why — 왜 등장했나
1) 정적 폰트의 곱셈 비용
전통적으로 한 폰트의 전체 weight·style은 별도 파일이었다:
Inter-Thin.woff2 (250KB)
Inter-ExtraLight.woff2 (250KB)
Inter-Light.woff2 (250KB)
Inter-Regular.woff2 (250KB)
Inter-Medium.woff2 (250KB)
Inter-SemiBold.woff2 (250KB)
Inter-Bold.woff2 (250KB)
Inter-ExtraBold.woff2 (250KB)
Inter-Black.woff2 (250KB)
+ 9 italic 버전
= 18 파일, 4.5MB대부분 사이트가 2-3 weight만 쓰면서도 디자이너가 “오늘은 600이 필요” 라며 weight를 추가하면 250KB 다운로드 추가.
2) 디자인 공간의 연속성
폰트 디자이너는 사실 100, 200, ..., 900 같은 9개 점이 아니라 연속적인 디자인 공간을 만든다. 9개는 대표 스냅샷일 뿐. Variable font는 이 연속 공간 전체를 한 파일에 담는다.
3) 모바일 시대의 대역폭 제약
LTE/3G에서 4MB 폰트는 5-10초 다운로드. Variable font는 250-500KB로 같은 표현력 → 자원 1/9.
How — Variable font의 5개 표준 축
OpenType은 5개의 등록된 축 을 정의한다 — 모든 variable font가 따르는 표준 이름.
| 축 | CSS 속성 | 의미 | 일반 범위 |
|---|---|---|---|
wght | font-weight | weight (굵기) | 100..900 |
wdth | font-stretch | width (폭) | 50..200% |
slnt | font-style: oblique | slant (기울기, 각도) | -14..14deg |
ital | font-style: italic | italic (이탤릭 켜기) | 0 또는 1 |
opsz | font-optical-sizing | optical size (시각 크기) | 8..144 |
추가로 폰트 제작자가 커스텀 축을 정의할 수 있다 (GRAD, MONO, XOPQ 등 — 4글자 대문자).
How — CSS로 축 제어하는 두 가지 방법
1) High-level 속성 (권장)
.heading {
font-family: "Inter";
font-weight: 650; /* wght 축 */
font-stretch: 110%; /* wdth 축 */
font-style: italic; /* ital 축 */
font-optical-sizing: auto; /* opsz 축 — font-size에 자동 매핑 */
}- 브라우저가 해당하는 variation 축에 자동 매핑.
font-weight: 650같은 비표준 정수 값도 가능.font-optical-sizing: auto는 font-size에 따라 opsz를 자동 조정 (작은 크기엔 두꺼운 stroke, 큰 크기엔 얇은 stroke).
2) Low-level font-variation-settings
.heading {
font-family: "Inter";
font-variation-settings:
"wght" 650,
"wdth" 110,
"slnt" -8,
"GRAD" 50; /* 커스텀 축 */
}- 커스텀 축을 쓰려면 반드시 이 속성.
- 주의:
font-variation-settings는 이전 값을 모두 덮어쓴다 — 한 축만 바꾸려고 해도 모든 축을 다시 적어야 함.
3) 두 방식 혼용 시 충돌
.a {
font-weight: 700;
font-variation-settings: "wght" 400; /* 700? 400? */
}→ font-variation-settings가 이긴다 (low-level이 high-level을 덮어씀). 따라서 일반적인 weight 변경은 font-weight로, 커스텀 축은 font-variation-settings로.
How — @font-face 등록
@font-face {
font-family: "Inter";
src: url("/fonts/InterVariable.woff2") format("woff2-variations");
font-weight: 100 900; /* wght 축 범위 */
font-stretch: 75% 125%; /* wdth 축 범위 */
font-style: oblique -14deg 0deg; /* slnt 축 범위 (italic만 0deg) */
font-display: swap;
}- weight·stretch·style 모두 범위 (2개 값) 로 명시.
- format:
"woff2-variations"(구) 또는"woff2" tech("variations")(CSS Fonts Level 4).
Italic이 별도 파일인 경우
@font-face {
font-family: "Inter";
src: url("/fonts/InterVariable.woff2") format("woff2-variations");
font-weight: 100 900;
font-style: normal;
}
@font-face {
font-family: "Inter";
src: url("/fonts/InterVariable-Italic.woff2") format("woff2-variations");
font-weight: 100 900;
font-style: italic;
}브라우저는 font-style: italic이 등장하면 두 번째 파일을 받는다.
What — 파일 크기 비교
| 폰트 | 정적 (9 weight × 2 style) | Variable | 절감 |
|---|---|---|---|
| Inter (Latin) | 약 2.25MB | 약 350KB | 84% |
| Roboto Flex | 약 3MB | 약 1.5MB (축 12개) | 50% |
| Pretendard (Latin+Korean) | 약 27MB (3MB × 9) | 약 2.4MB | 91% |
| Recursive | 약 2.8MB | 약 500KB (5축) | 82% |
한글 폰트일수록 variable의 이득이 크다 — 글리프 수가 많아 정적 폰트의 곱셈 비용이 커지기 때문.
What — 흥미로운 축 활용
1) opsz (Optical Sizing) — 자동
:root { font-optical-sizing: auto; }
h1 { font-size: 48px; } /* opsz 48 — 세련된 얇은 획 */
p { font-size: 14px; } /* opsz 14 — 가독성 위해 두꺼운 stroke */폰트 디자이너가 크기별로 다른 글자 모양을 디자인해 둔다 (Roboto Serif, Source Serif Pro 등). auto는 font-size에 자동 매핑.
2) wght로 hover 애니메이션
.button {
font-family: "Inter";
font-weight: 400;
transition: font-weight 200ms;
}
.button:hover {
font-weight: 600;
}- 정적 폰트로는 깜빡 바뀐다 (400.woff2 → 600.woff2 스왑).
- Variable font는 부드럽게 두꺼워진다 — 폰트 엔진이 보간.
3) slnt로 미세 기울임
em {
font-style: oblique -8deg; /* 8도만 기울임 — 진짜 italic이 아니라 oblique */
}- 정적 italic은 0 or 1.
- Variable의
slnt는 0~14도 사이 어디든.
4) Recursive의 MONO 축
code {
font-family: "Recursive";
font-variation-settings: "MONO" 1; /* 0 = 프로포셔널, 1 = 모노스페이스 */
}- 한 폰트가 프로포셔널 ↔ 모노 사이를 연속.
MONO 0.5같은 반-모노 도 가능.
What — font-variation-settings 변수와 합치기
:root {
--font-weight: 400;
--font-width: 100;
}
body {
font-variation-settings: "wght" var(--font-weight), "wdth" var(--font-width);
}
.heading {
--font-weight: 700;
--font-width: 110;
}- 디자인 시스템에서 축 값을 토큰화.
@property로 타입 선언하면 애니메이션도 가능:
@property --font-weight {
syntax: "<number>";
initial-value: 400;
inherits: true;
}
.morph {
transition: --font-weight 300ms;
}
.morph:hover {
--font-weight: 700;
}What-if — 잘못 쓰면
1) font-variation-settings의 덮어쓰기 함정
.heading {
font-variation-settings: "wght" 700;
}
.heading.italic {
font-variation-settings: "slnt" -10; /* wght이 사라진다! */
}→ slnt만 설정하면서 wght이 기본값으로 리셋된다. 항상 모든 축을 다시 적거나, 변수로 합성:
.heading {
--w: 700;
--s: 0;
font-variation-settings: "wght" var(--w), "slnt" var(--s);
}
.heading.italic { --s: -10; }2) 정적 + variable 혼용 with 같은 family
@font-face { font-family: "Inter"; src: url("inter-var.woff2") ...; font-weight: 100 900; }
@font-face { font-family: "Inter"; src: url("inter-bold.woff2"); font-weight: 700; }
/* font-weight: 700 시 브라우저가 어느 파일을 쓸지 불명확 */→ Variable이 있으면 정적은 모두 제거.
3) 브라우저 미지원 fallback 없음
@font-face {
font-family: "Inter";
src: url("/inter-var.woff2") format("woff2-variations");
/* 구식 브라우저는 못 읽음 */
}→ 2024년 기준 IE만 미지원 (woff2-variations). IE 지원 필요하면 정적 fallback:
@font-face {
font-family: "Inter";
src: url("/inter-var.woff2") format("woff2-variations"),
url("/inter-regular.woff2") format("woff2");
}4) 모든 축을 변동 가능하게
.text {
transition: font-variation-settings 300ms; /* 모든 축이 동시에 변동 */
}→ 한 축만 변동하고 싶을 땐 --var + transition: --var로 축 단위 제어.
Insight — 흥미로운 이야기
“Variable Font는 1990년대 Adobe Multiple Master의 부활”
1991년 Adobe는 Multiple Master 폰트 기술을 발표했다 — 여러 master 디자인 사이를 보간하는 변형 폰트. 디자인적으로는 혁신이었지만 너무 빨랐다 — OS 지원 부족, 디자이너의 학습 곡선, 인쇄 워크플로 부재로 1999년 Adobe가 단종. 18년이 지난 2016년 ATypI 컨퍼런스에서 Adobe·Apple·Google·Microsoft 4사가 OpenType 1.8 + Variable Font를 공동 발표 — Multiple Master의 부활이었다. 이번엔 웹이라는 사용처가 있었고, 대역폭 압박이라는 필요성이 있었다. 기술이 시대를 30년 앞서면 죽고, 시대가 따라잡으면 부활한다.
“Inter는 variable font 시대의 첫 성공”
2016년 스웨덴의 Rasmus Andersson(전 Spotify·Figma)이 Figma UI 폰트로 쓰려고 Inter를 디자인했다. 2018년 Inter v3에서 variable 버전 (
InterVariable.woff2) 을 추가 — 약 350KB로 100..900 weight 전체. Figma·Linear·Vercel·GitHub Primer가 채택했고, 2024년 모든 모던 SaaS 디자인 시스템의 기본 폰트가 됐다. Inter Display 라는 별도 display-size 최적화 variant도 있는데, 이건opsz축의 정적 export. 한 사람의 디자이너가 만든 폰트가 변하는 폰트의 시대를 열었다.
요약 + Mermaid
- Variable font는 한 파일이 N차원 축을 가짐 —
wght/wdth/slnt/ital/opsz+ 커스텀. - 정적 9개 weight = ~2.25MB, Variable = ~350KB → 6-9배 압축, 비표준 weight도 표현 가능.
- High-level
font-weight/font-stretch또는 low-levelfont-variation-settings. font-variation-settings는 이전 값을 덮어씀 → 변수로 축 분리해서 합성.font-optical-sizing: auto로 크기별 글자 모양 자동 전환.
다음 문서 → 05-text-properties: 글자가 정해진 다음 — 텍스트가 어떻게 흐르는가.