# Typography 서체와 글자 크기·굵기·행간으로 만드는 읽기의 위계입니다. > 원본: `03_ASSET_GUIDE/foundations/typography.js` · 값: `03_ASSET_GUIDE/styles/tokens.css` (`--- Typography ---` 절) > status **`draft`** · specSource **`proposed`** — 이 등급을 확인하지 않고 수치를 확정 스펙으로 쓰면 안 됩니다. | 단계 | 역할 | 예시 | |---|---|---| | **Primitive** | 서체 스택 · 크기 스케일 `t1`–`t12` · 굵기 4단계 | `--atom-t5-size` = `15px` | | **Semantic** | 없음 — 스케일 단계마다 역할(본문 기본·캡션·제목)이 정해져 있습니다(아래 2절) | 본문 기본 → `t5` | > [!NOTE] > **컴포넌트 CSS 는 아직 크기 · 굵기 토큰을 쓰지 않습니다** > 크기 · 굵기 스케일은 `tokens.css` 에 토큰으로 있지만, `base.css` · `chrome.css` · `doc.css` · `elements/*.css` 는 같은 값을 직접 씁니다. > 아래 실측 표는 그 코드를 실측해 정리한 것입니다. --- ## 1. Font family | Token | 스택 | 용도 | |---|---|---| | `--atom-font-sans` | `"Pretendard Variable"` → `Pretendard` → `-apple-system` → `BlinkMacSystemFont` → `system-ui` → `Roboto` → `"Helvetica Neue"` → `"Segoe UI"` → `"Apple SD Gothic Neo"` → `"Noto Sans KR"` → `"Malgun Gothic"` → `sans-serif` | 모든 본문과 UI | | `--atom-font-mono` | `ui-monospace` → `SFMono-Regular` → `"SF Mono"` → `Menlo` → `Consolas` → `"Liberation Mono"` → `monospace` | 코드, 토큰 이름, 표의 타입 열 | 스택 앞쪽에 **Pretendard** 를, 뒤쪽에 OS 기본 한글 서체(Apple SD Gothic Neo · Noto Sans KR · Malgun Gothic)를 두어 한글이 어느 환경에서든 시스템 서체로 떨어지게 했습니다. --- ## 2. Primitive tokens ### 크기 스케일 크기(`-size`)와 행간(`-line`)은 따로 덮어쓸 수 있도록 별도 토큰입니다. 자간(`-tracking`)은 `t7` 부터만 있고, 그 아래는 `normal` 입니다. | 단계 | 크기 (`-size`) | 행간 (`-line`) | 자간 (`-tracking`) | 역할 | |---|---|---|---|---| | `t1` | 11px | 1.4 | — | 표식, 마이크로 라벨 | | `t2` | 12px | 1.5 | — | 캡션, 메타 | | `t3` | 13px | 1.5 | — | 보조 본문, 폼 라벨 | | `t4` | 14px | 1.55 | — | 본문 소 | | `t5` | 15px | 1.7 | — | **본문 기본** | | `t6` | 16px | 1.7 | — | 본문 대 | | `t7` | 18px | 1.5 | `-0.01em` | 소제목 (h4) | | `t8` | 20px | 1.45 | `-0.01em` | 카드 제목 | | `t9` | 24px | 1.45 | `-0.01em` | 제목 (h2) | | `t10` | 32px | 1.25 | `-0.02em` | 페이지 제목 | | `t11` | 44px | 1.15 | `-0.02em` | 페이지 제목 (넓은 화면) | | `t12` | 60px | 1.1 | `-0.025em` | 디스플레이 | 토큰 이름은 `--atom-t{n}-size` · `--atom-t{n}-line` · `--atom-t{n}-tracking` 입니다. ### 굵기 스케일 | Token | Value | 이름 | |---|---|---| | `--atom-weight-regular` | `400` | Regular | | `--atom-weight-medium` | `500` | Medium | | `--atom-weight-semibold` | `600` | SemiBold | | `--atom-weight-bold` | `700` | Bold | 300 은 `.atom-page-header__subtitle` 과 `.atom-doc__description` 두 곳에서만 쓰여 스케일에 넣지 않았습니다. ### 실측 — 크기 아래는 저장소 전체에서 쓰이는 크기와 그 역할입니다. | 크기 | 사용 횟수 | 역할 | 대표 위치 | |---|---|---|---| | 10px | 1 | 최소 표식 | `.atom-badge--size_small` | | 11px | 6 | 표식·마이크로 라벨 | `.atom-badge`, `.atom-select__group-label` | | 12px | 13 | 캡션·메타 | `.atom-field__footer`, `.atom-toc__title` | | 13px | 16 | 보조 본문·폼 라벨 | `.atom-field__label`, `.atom-toc`, `.atom-code code` | | 14px | 17 | 본문 소 | `.atom-table`, `.atom-nav-link`, `.atom-callout` | | 15px | 14 | **본문 기본** | `.atom-prose`, `.atom-button`, `.atom-text-input` | | 16px | 10 | 본문 대 | `body`, `.atom-button--size_large` | | 18px | 1 | 소제목 (h4) | `.atom-section--level_3 > .atom-section__heading` | | 20px | 2 | 카드 제목 (넓은 화면) | `.atom-component-card__title` | | 22px | 1 | 워드마크 | `.atom-site-header__wordmark` | | 24px | 1 | 제목 (h2) | `.atom-section--level_2 > .atom-section__heading` | | 32px (`2rem`) | 2 | 페이지 제목 | `.atom-doc__title`, `.atom-page-header__title` | | 44px (`2.75rem`) | 1 | 페이지 제목 (넓은 화면) | `.atom-doc__title` | | 48px (`3rem`) | 1 | 디스플레이 | `.atom-page-header__title` | | 60px (`3.75rem`) | 1 | 디스플레이 (가장 넓은 화면) | `.atom-page-header__title` | 11.5px(`.atom-demo-label`) · 12.5px(`.atom-table__type`) 두 값은 스케일에 없는 반쪽 값입니다. 각각 11px · 12px 에 흡수할 수 있습니다. ### 실측 — 굵기 | 값 | 이름 | 쓰임 | |---|---|---| | 300 | Light | 페이지 부제목 (`.atom-page-header__subtitle`), 문서 설명 (`.atom-doc__description`) | | 400 | Regular | 본문 기본 | | 500 | Medium | 모든 제목(`h1`–`h4` 기본값), 현재 항목 표시 | | 600 | SemiBold | 버튼·배지 라벨, 폼 라벨, 표 헤더, `strong` | | 700 | Bold | 워드마크, Do/Don't 라벨, 콜아웃 제목 | ### 실측 — 행간 | 값 | 대상 | |---|---| | 1 | 한 줄로 고정되는 것 — 버튼 라벨, 배지, 워드마크 | | 1.1 · 1.15 | 대형 제목 | | 1.25 | **기본값** — `body`, `h1`–`h4` (`base.css`) | | 1.35 · 1.4 | 데모 라벨, 목차 링크, 폼 라벨 | | 1.45 | 컴포넌트 본문 — 입력·체크박스·라디오 | | 1.5 | 폼 푸터 | | 1.6 · 1.65 | 콜아웃, 코드 블록 | | 1.7 | **산문** — `.atom-prose`, `.atom-doc-list` | ### 실측 — 자간 | 값 | 대상 | |---|---| | `-0.025em` | 60px 페이지 제목 | | `-0.02em` | 32px 문서 제목, 20px 푸터 태그라인 | | `-0.01em` | 섹션 제목 (18–24px) | | `0.06em` | 워드마크 (대문자) | **글자가 클수록 자간을 더 조입니다.** 큰 글자는 글자 사이가 실제보다 벌어져 보이기 때문에 음수 자간으로 되돌립니다. 본문 크기(16px 이하)에는 자간을 주지 않습니다. 대문자는 붙어 보이므로 대문자 워드마크에만 양수 자간을 줍니다. --- ## 3. Semantic tokens ATOM 은 타이포그래피에 역할 토큰(`text.body` 같은 이름)을 두지 않습니다. 스케일 단계가 곧 역할입니다. | 역할 | 단계 | |---|---| | 표식·마이크로 라벨 | `t1` | | 캡션·메타 | `t2` | | 보조 본문·폼 라벨 | `t3` | | 본문 소 | `t4` | | **본문 기본** | `t5` | | 본문 대 | `t6` | | 소제목 (h4) · 카드 제목 · 제목 (h2) | `t7` · `t8` · `t9` | | 페이지 제목 · 디스플레이 | `t10` · `t11` · `t12` | ### 규칙 1. **크기로 위계를 만들고, 굵기는 아낍니다** — 제목은 500, 본문 안 강조는 600 까지만. 2. **한 화면에서 크기는 3–4단계까지** — 제목 24px · 본문 15px · 캡션 12px 세 단계로 충분합니다. 3. **한국어 문장은 단어 중간에서 끊지 않습니다** — `.atom-break-keep` (`word-break: keep-all` + `overflow-wrap: break-word`). --- ## 4. Design tokens (JSON) [W3C Design Tokens (DTCG)](https://tr.designtokens.org/format/) 형식입니다. 경로는 `--atom-font-*` → `font.*`, `--atom-t{n}-*` → `type.t{n}.*`, `--atom-weight-*` → `font-weight.*` 입니다. ```json { "font": { "$type": "fontFamily", "sans": { "$value": ["Pretendard Variable", "Pretendard", "-apple-system", "BlinkMacSystemFont", "system-ui", "Roboto", "Helvetica Neue", "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "sans-serif"] }, "mono": { "$value": ["ui-monospace", "SFMono-Regular", "SF Mono", "Menlo", "Consolas", "Liberation Mono", "monospace"] } }, "font-weight": { "$type": "fontWeight", "regular": { "$value": 400 }, "medium": { "$value": 500 }, "semibold": { "$value": 600 }, "bold": { "$value": 700 } }, "type": { "t1": { "size": { "$type": "dimension", "$value": "11px" }, "line": { "$type": "number", "$value": 1.4 } }, "t2": { "size": { "$type": "dimension", "$value": "12px" }, "line": { "$type": "number", "$value": 1.5 } }, "t3": { "size": { "$type": "dimension", "$value": "13px" }, "line": { "$type": "number", "$value": 1.5 } }, "t4": { "size": { "$type": "dimension", "$value": "14px" }, "line": { "$type": "number", "$value": 1.55 } }, "t5": { "size": { "$type": "dimension", "$value": "15px" }, "line": { "$type": "number", "$value": 1.7 } }, "t6": { "size": { "$type": "dimension", "$value": "16px" }, "line": { "$type": "number", "$value": 1.7 } }, "t7": { "size": { "$type": "dimension", "$value": "18px" }, "line": { "$type": "number", "$value": 1.5 }, "tracking": { "$type": "dimension", "$value": "-0.01em" } }, "t8": { "size": { "$type": "dimension", "$value": "20px" }, "line": { "$type": "number", "$value": 1.45 }, "tracking": { "$type": "dimension", "$value": "-0.01em" } }, "t9": { "size": { "$type": "dimension", "$value": "24px" }, "line": { "$type": "number", "$value": 1.45 }, "tracking": { "$type": "dimension", "$value": "-0.01em" } }, "t10": { "size": { "$type": "dimension", "$value": "32px" }, "line": { "$type": "number", "$value": 1.25 }, "tracking": { "$type": "dimension", "$value": "-0.02em" } }, "t11": { "size": { "$type": "dimension", "$value": "44px" }, "line": { "$type": "number", "$value": 1.15 }, "tracking": { "$type": "dimension", "$value": "-0.02em" } }, "t12": { "size": { "$type": "dimension", "$value": "60px" }, "line": { "$type": "number", "$value": 1.1 }, "tracking": { "$type": "dimension", "$value": "-0.025em" } } } } ``` --- ## 5. CSS 적용 ```css /* 지금 (하드코딩) */ .atom-prose { font-size: 15px; line-height: 1.7; } /* 토큰 사용 */ .atom-prose { font-size: var(--atom-t5-size); line-height: var(--atom-t5-line); } ``` ```html
그룹 안 간격은 그룹 사이 간격보다 좁게 둡니다.
``` --- ## 6. 사용 가이드 ### 크기로 위계를 만들고, 굵기는 아낍니다 한글은 굵은 웨이트에서 획이 뭉칩니다. 강조가 필요하면 굵기를 올리기 전에 크기를 먼저 고려하고, 굵기는 500·600 두 단계 안에서 해결합니다. - ✅ **Do** 제목은 500, 본문 안 강조는 600 까지만 씁니다. - ❌ **Don't** 본문 문장 전체를 700 으로 굵게 만들지 않습니다. ### 한 화면에서 크기는 3–4단계까지 한 화면에서는 제목·본문·보조 세 단계로 충분합니다. 넷을 넘으면 위계가 읽히지 않습니다. - ✅ **Do** 제목 24px · 본문 15px · 캡션 12px 세 단계로 구성합니다. - ❌ **Don't** 한 화면에 6가지 크기를 섞지 않습니다. ### 한국어 문장은 단어 중간에서 끊지 않습니다 브라우저 기본값은 한글을 글자 단위로 줄바꿈합니다. 단어가 두 줄에 걸쳐 잘리면 읽기 흐름이 끊깁니다. `.atom-break-keep` (`word-break: keep-all`) 을 붙입니다. - ✅ **Do** 한국어 문장 컨테이너에 `.atom-break-keep` 을 붙입니다. - ❌ **Don't** 긴 한국어 문장을 기본 줄바꿈에 맡기지 않습니다. `overflow-wrap: break-word` 를 함께 두어 URL 처럼 끊을 곳이 없는 긴 문자열은 넘치지 않게 합니다. `.atom-break-keep` 이 이미 둘을 함께 선언합니다. ### 한 줄은 너무 길지 않게 한 줄이 길면 다음 줄의 시작점을 찾기 어렵습니다. 라틴 기준 70자 안팎이 권장 범위이고, 한글은 글자 폭이 넓어 그 절반 정도가 같은 물리적 길이입니다. 문서 본문의 폭 제한(`doc.css` 의 본문 폭 규칙)이 이 역할을 합니다. - ✅ **Do** 산문 영역에 최대 폭을 둡니다. - ❌ **Don't** 본문이 화면 폭 전체로 늘어나게 두지 않습니다. ### 왼쪽 정렬, 들여쓰기 없이 가운데 정렬은 두 줄을 넘으면 읽기 어려워지고, 양쪽 정렬(`justify`)은 단어 사이에 불규칙한 공백을 만듭니다. 문단 구분은 들여쓰기가 아니라 간격으로 합니다. - ✅ **Do** 본문은 왼쪽 정렬, 문단 사이는 `margin` 으로 띄웁니다. - ❌ **Don't** `text-align: justify` 나 `text-indent` 를 쓰지 않습니다. 가운데 정렬은 한 줄짜리 제목·빈 상태 문구처럼 짧은 텍스트에만 씁니다. ### 밑줄은 링크에만 밑줄은 링크를 나타내므로 강조에 쓰면 링크로 오인됩니다. 강조에는 굵기나 색을 씁니다. ### 숫자를 비교하는 자리에는 고정폭 숫자를 표나 목록에서 자릿수를 비교해야 한다면 `font-variant-numeric: tabular-nums` 를 씁니다. 비례폭 숫자는 1 이 좁아 세로 정렬이 어긋납니다. ### 기울임은 쓰지 않습니다 한글 서체에는 이탤릭이 없어서 브라우저가 글자를 기계적으로 기울이고, 획 모양이 고르지 않게 됩니다. 강조는 굵기로 합니다. ### 접근성 - **최소 크기** — 읽어야 하는 글자는 12px 이상으로 둡니다. 현재 10px 를 쓰는 곳은 `.atom-badge--size_small` 하나이고, 배지는 숫자·짧은 상태 표식이라 문장이 아닙니다. 문장을 10–11px 로 두지 않습니다. - **대비** — 글자 색은 [Color](./color.md) 의 기준을 따릅니다. 본문 4.5:1, 18px 이상 3:1. `--atom-fg-neutral-subtle` 은 2.57:1 이라 읽어야 하는 글자에 쓸 수 없습니다. - **확대** — 크기가 px 고정이라 브라우저 글자 크기 설정에 반응하지 않습니다. `rem` 으로 바꾸면 사용자 설정을 존중할 수 있지만, 컴포넌트 높이가 함께 밀리므로 스케일 도입과 함께 결정해야 하는 문제입니다. **현재는 사용자 글자 크기 설정이 본문에 반영되지 않습니다.** 브라우저 확대(전체 확대)는 정상 동작합니다. - **줄 간격** — WCAG 1.4.12 는 본문 행간을 글자 크기의 1.5배 이상으로 요구합니다. 산문 1.7 은 충족하지만, **`body` 기본값 1.25 와 컴포넌트 본문 1.45(입력·체크박스·라디오)는 이 기준에 못 미칩니다.** 한 줄짜리 라벨이라 실질적 영향은 없으나, 여러 줄이 되는 체크박스 설명에는 1.5 이상이 필요합니다. - **`h1`–`h4` 는 크기만이 아니라 실제 태그로** — 시각적 크기로만 제목을 만들면 스크린리더의 제목 탐색이 동작하지 않습니다. `doc.css` 의 `.atom-section__heading` 은 섹션 깊이에 따라 실제 `h2`–`h4` 로 렌더됩니다.