타이포그래피 스케일 시스템 — 가독성과 위계를 동시에 잡는 설계

디자인 시스템

타이포그래피디자인 시스템폰트스케일

이 글은 누구를 위한 것인가

  • 디자이너마다 폰트 크기를 다르게 쓰고 있어 일관성이 없는 팀
  • "이 텍스트를 얼마나 크게 해야 하나요?"라는 질문이 매번 나오는 환경
  • 반응형에서 타이포그래피 크기를 일일이 조정하는 작업이 반복되는 개발팀

타이포그래피 시스템이 없을 때 생기는 문제

"조금 더 크게", "좀 강조해 주세요" — 명확한 스케일이 없으면 폰트 크기가 13px, 14px, 15px, 16px이 혼재하게 된다. 결과는 시각적 위계 혼란, 일관성 없는 읽기 경험, 그리고 코드 전역에 흩어진 매직 넘버들이다.


1. 모듈러 스케일: 수학적 비율로 크기 결정

모듈러 스케일은 기준 크기와 비율(ratio)을 정의해 모든 폰트 크기를 수학적으로 도출한다.

주요 비율

비율 이름느낌
Minor Second1.067미세한 차이, 본문 중심
Major Second1.125부드러운 위계
Minor Third1.200균형 잡힌 위계
Major Third1.250뚜렷한 구분
Perfect Fourth1.333강한 위계, 마케팅 페이지
Golden Ratio1.618극적인 대비, 랜딩 페이지

대부분의 UI 시스템에서는 Minor Third(1.2) 또는 Major Third(1.25) 가 적합하다.

스케일 계산 예시 (기준 16px, 비율 1.25)

xs:   16 ÷ 1.25² = 10.24px → 10px
sm:   16 ÷ 1.25  = 12.8px  → 13px
base: 16px (기준)
lg:   16 × 1.25  = 20px
xl:   16 × 1.25² = 25px
2xl:  16 × 1.25³ = 31.25px → 31px
3xl:  16 × 1.25⁴ = 39px
4xl:  16 × 1.25⁵ = 48.83px → 49px

2. 토큰으로 표현하기

계산된 스케일을 디자인 토큰으로 정의한다.

:root {
  /* font-size */
  --text-xs:   0.625rem;   /* 10px */
  --text-sm:   0.8125rem;  /* 13px */
  --text-base: 1rem;       /* 16px */
  --text-lg:   1.25rem;    /* 20px */
  --text-xl:   1.5625rem;  /* 25px */
  --text-2xl:  1.9375rem;  /* 31px */
  --text-3xl:  2.4375rem;  /* 39px */
  --text-4xl:  3.0625rem;  /* 49px */

  /* line-height */
  --leading-tight:  1.25;
  --leading-snug:   1.375;
  --leading-normal: 1.5;
  --leading-relaxed: 1.625;
  --leading-loose:  2.0;

  /* letter-spacing */
  --tracking-tight:  -0.025em;
  --tracking-normal: 0em;
  --tracking-wide:   0.025em;
  --tracking-wider:  0.05em;
  --tracking-widest: 0.1em;

  /* font-weight */
  --font-normal:    400;
  --font-medium:    500;
  --font-semibold:  600;
  --font-bold:      700;
}

3. 줄 높이와 자간: 자주 놓치는 설정

폰트 크기만 정하고 줄 높이와 자간을 방치하면 가독성이 떨어진다.

줄 높이 가이드라인

용도줄 높이이유
제목 (24px+)1.1~1.25큰 텍스트는 줄 간격 좁아도 읽힘
소제목 (18~24px)1.25~1.375중간 균형
본문 (14~18px)1.5~1.625긴 문장 가독성
캡션 (10~13px)1.4~1.5작은 텍스트는 약간 넓게
코드1.5~1.7코드 블록 판독성

핵심: 폰트가 클수록 줄 높이를 낮추고, 작을수록 높인다.

자간 가이드라인

용도자간
대형 제목 (32px+)-0.02em ~ -0.04em (좁게)
소제목0 (기본)
본문0 ~ +0.01em
전체 대문자 (ALL CAPS)+0.05em ~ +0.1em (넓게)
캡션·레이블+0.01em ~ +0.03em

대문자로만 구성된 레이블은 반드시 자간을 넓혀야 읽기 편하다.


4. 시맨틱 텍스트 스타일

숫자 스케일(text-2xl)을 직접 쓰는 것보다 역할 기반 시맨틱 스타일을 정의하면 일관성이 생긴다.

/* 시맨틱 텍스트 스타일 */
.text-display {
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.text-heading-1 {
  font-size: var(--text-3xl);
  font-weight: var(--font-bold);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.text-heading-2 {
  font-size: var(--text-2xl);
  font-weight: var(--font-semibold);
  line-height: var(--leading-snug);
}

.text-heading-3 {
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  line-height: var(--leading-snug);
}

.text-body-lg {
  font-size: var(--text-lg);
  font-weight: var(--font-normal);
  line-height: var(--leading-relaxed);
}

.text-body {
  font-size: var(--text-base);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
}

.text-body-sm {
  font-size: var(--text-sm);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
}

.text-caption {
  font-size: var(--text-xs);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
  letter-spacing: var(--tracking-wide);
}

.text-label {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
}

5. 유체 타이포그래피: 뷰포트에 따라 부드럽게 변화

모바일과 데스크탑에 서로 다른 폰트 크기를 브레이크포인트로 전환하면 크기가 갑자기 바뀐다. 유체 타이포그래피는 뷰포트 너비에 따라 폰트 크기가 연속적으로 변화한다.

/* clamp(최솟값, 선형 함수, 최댓값) */
.text-heading-1 {
  font-size: clamp(1.75rem, 3vw + 1rem, 3rem);
  /* 뷰포트 320px: ~1.75rem (28px) */
  /* 뷰포트 768px: ~2.3rem */
  /* 뷰포트 1280px+: 3rem (48px) */
}

계산 공식:

선형 함수 = 기울기vw + 절편rem

기울기 = (최대 크기 - 최소 크기) / (최대 뷰포트 - 최소 뷰포트) × 100
절편 = 최소 크기 - 기울기 × (최소 뷰포트 / 100)

일일이 계산하지 않고 Utopia 같은 도구로 자동 생성할 수 있다.


6. 한국어 타이포그래피 고려사항

한국어는 영어와 다른 특성이 있어 별도 조정이 필요하다.

줄 높이

한국어 글자는 세로 폭이 넓다. 영어 기준 1.5 줄 높이를 그대로 쓰면 답답하게 느껴진다. 한국어 본문은 1.6~1.8 줄 높이가 더 편하다.

폰트 패밀리 스택

:root {
  --font-sans:
    'Pretendard Variable',  /* 한국어 가변 폰트 (권장) */
    'Pretendard',
    -apple-system,
    BlinkMacSystemFont,
    system-ui,
    'Apple SD Gothic Neo',
    'Noto Sans KR',
    sans-serif;
}

word-break

한국어는 단어 사이 공백이 없어 긴 단어가 줄바꿈 없이 컨테이너를 넘칠 수 있다.

body {
  word-break: keep-all;  /* 단어 단위로 줄바꿈 (한국어 권장) */
  overflow-wrap: break-word;  /* 컨테이너 넘침 방지 폴백 */
}

맺으며

타이포그래피 시스템은 한 번 정해두면 디자이너와 개발자 모두 "이 텍스트 몇 px로 하면 돼요?"라는 질문 없이 시맨틱 스타일 이름만으로 소통할 수 있게 해준다.

모듈러 스케일로 크기를 정하고, 줄 높이와 자간까지 토큰에 포함시키고, 한국어 특성에 맞게 조정하면 충분하다. Figma의 Text Styles에 동일한 이름으로 정의해두면 디자인-코드 간 언어가 일치한다.