타이포그래피
진행 중 (Typography — work in progress)
- 폰트 패밀리·문자 스케일 토큰은 정의돼 있으나 실제 코드는 대부분 하드코딩(예:
font-size: 13px64건 — 공백 없는 표기 포함)으로 토큰을 거치지 않습니다. - 두 가지 토큰 체계가 공존합니다 (
--typo-*intokens.cssvs--text-*indesign-system.css). 단순 중복이 아니라 의도된 분리 —--text-*(@theme)는 Tailwind tree-shaking으로 안 쓰는 등급이 빌드:root에서 잘리므로(빌드 확인됨:--text-h1없음), HTML 기본 태그(<h1>등)는 항상 출력되는--typo-*(:root)를 써야 함. 병합 ❌ — 아래 검토 필요 #1 참고. - font-weight 토큰 정의 완료 (
--font-weight-regular/medium/semibold/bold= 400/500/600/700, design-system.css + 사용 18회). 단, 앱 코드의font-weight:NNN하드코딩 토큰 치환은 미완. - 검토 필요한 항목과 미정리 영역은 본 페이지 검토 필요 사항과 토큰 미사용 사용처를 참고하세요.
규칙 (강제) · 코딩 에이전트용 — 사람은 접힌 채로 두어도 됩니다
타이포그래피 강제 규칙. 상세·토큰표·미정리 현황은 아래 본문.
- 사용 우선순위: ① Tailwind 유틸(
text-h1·text-b5·text-c2) → ②.typo-*클래스(기존 코드 호환) → ③ CSS 변수(var(--text-b5)/var(--typo-h1-size), HTML 기본 태그 매핑·동적 스타일 시) → ④ 하드코딩 지양(font-size: 13px). 토큰으로 표현 가능하면 토큰. - 스케일 12단계(모두 line-height
1.4· letter-spacing = 크기의 −1%): H1 32 · H2 28 · H3 24 · H4 22 · H5 20 · B2 18 · B3 16 · B4 14 · B5 13 · B6 12 · C1 11 · C2 10. B1(19px)은 없음(미정). - ⚠️ 두 토큰 체계를 합치지 말 것.
--typo-*(tokens.css,:root) = HTML 기본 태그(<h1>,<p>,<code>) 기본값 층으로 tree-shaking 안 됨.--text-*(design-system.css,@theme) = Tailwind 유틸 생성용으로 미사용 등급은 빌드에서 제거됨. 기본 태그를var(--text-h1)로 바꾸면 값이 사라져 깨짐(빌드 확인). 값 중복은 남지만 의도된 분리. - font-weight 토큰 사용:
--font-weight-regular/medium/semibold/bold= 400/500/600/700 (정의 완료). 새 코드에서font-weight: 600하드코딩 지양. - 숫자 표기: 데이터 숫자는 Inter 기본.
tabular-nums는 자릿수가 세로로 정렬되는 곳만(표의 숫자 열·쌓인 금액·시간) — 단독 인라인 숫자엔 쓰지 말 것. Tailwind 기본 유틸tabular-nums사용(새 토큰/클래스 만들지 말 것). font-mono금지 영역: 사번·코드 등 데이터 식별자에 mono 금지(Inter 사용).--font-mono는 코드 블록(<code>/<pre>)·키보드 단축키 전용.- 토큰에 없는 크기(15px · 9px · 8px · 7px)는 미정 상태 — 새로 도입하지 말고 인접 토큰(B4 14 / B3 16 / C2 10)으로 흡수.
- 폰트 패밀리 하드코딩은 이메일·PDF/인쇄·TinyMCE 등 CSS 변수 미지원 컨텍스트에서만 허용(본문 D절 명단). 그 외엔
--font-app/--font-inter등 토큰. - 모바일 화면 배율(employee-app): 웹은 정의 스케일(×1.0) 기준으로 개발, 모바일은
zoom으로 화면 전체를 비례 확대. 디폴트=기본(×1.2), 단계 = 작게(×1.0)·기본(×1.2)·크게(×1.4). 상세·미리보기: 모바일 화면 배율.
단일 출처 (현재 구조)
packages/static/styles/
├── tokens.css ← --typo-* + @font-face + .typo-* utility class
└── design-system.css ← --text-* + --font-* (Tailwind @theme)
tokens.css를 @import해서 합쳐서 노출검증 결과 — 단순 단일화 불가: 두 파일에 --typo-h1-size(tokens.css)와 --text-h1(design-system.css)이 같은 값(32px)으로 정의돼 있으나, --text-*는 @theme이라 Tailwind가 미사용 등급을 빌드 :root에서 제거합니다(빌드 산출물에서 --text-h1 부재 확인). 따라서 HTML 기본 태그 defaults는 --typo-*(:root, tree-shaking 안 됨)에 의존해야 하며, var(--text-h1)로 치환하면 값이 사라져 깨집니다. 값 중복은 남지만 메커니즘이 달라 의도적으로 유지(--typo = :root 기본값 / --text = Tailwind 유틸 생성).
폰트 패밀리
@font-face는 packages/static/styles/tokens.css:8-56에 정의돼 있고, 파일은 packages/static/fonts/에 위치합니다.
| Token | Family | 로드된 파일 | Weight |
|---|---|---|---|
--font-inter | InterVariable | fonts/Inter/InterVariable.woff2 (+Italic) | 100–900 (variable) |
--font-poppins | Poppins | Poppins-Regular/Medium/SemiBold/Bold.woff2 | 400 · 500 · 600 · 700 |
--font-pretendard | Pretendard Variable | fonts/Pretendard/PretendardVariable.woff2 | 100–900 (variable) |
--font-mono | source-code-pro, Menlo, Monaco, Consolas, Courier New | — | (system fallback) |
App default 스택 (--font-app)
전체 앱이 기본으로 사용하는 fallback 체인 — tokens.css:70-72:
InterVariable → Pretendard Variable → Noto Sans Symbols → Poppins
→ system-ui → -apple-system → Segoe UI → Roboto
→ Noto Sans KR → Apple SD Gothic Neo → Malgun Gothic → sans-serif영문은 Inter, 한글은 Pretendard, 이모지는 Noto Sans Symbols, Windows·macOS 시스템 폰트 fallback 순서.
미리보기
Inter — The quick brown fox jumps over the lazy dog. 1234567890
Pretendard — 안녕하세요. 한글 본문 미리보기입니다. 1234567890
Poppins — Hereby Design System
Mono — const greeting = "hello";
중복 해소됨 (2026-06-18): --ds-font-family(design-system.css:268)는 --font-app과 동일한 literal을 베껴 갖고 있었으나, 이제 --ds-font-family: var(--font-app) 별칭으로 정리돼 값이 동기화됩니다(literal 단일화). --font-app 자체는 Tailwind @theme에 있어야 font-app 유틸을 생성하므로 그대로 유지. (--ds-font-family는 :root라 tree-shaking 영향 없음, --font-app도 사용돼 항상 출력 → 안전)
Typography scale — 정의된 12단계
각 단계는 size + line-height + letter-spacing 세트로 정의돼 있고, 모두 line-height 1.4 · letter-spacing −1% of size 규칙을 따릅니다.
미리보기
토큰 표
| 등급 | --text-* (design-system.css) | --typo-* (tokens.css) | Tailwind utility | .typo-* class | 크기 |
|---|---|---|---|---|---|
| H1 | --text-h1 | --typo-h1-size/-tracking/-lh | text-h1 | .typo-h1 | 32px |
| H2 | --text-h2 | --typo-h2-* | text-h2 | .typo-h2 | 28px |
| H3 | --text-h3 | --typo-h3-* | text-h3 | .typo-h3 | 24px |
| H4 | --text-h4 | --typo-h4-* | text-h4 | .typo-h4 | 22px |
| H5 | --text-h5 | --typo-h5-* | text-h5 | .typo-h5 | 20px |
| B1 | (없음) | (없음) | — | — | (검토 필요) |
| B2 | --text-b2 | --typo-b2-* | text-b2 | .typo-b2 | 18px |
| B3 | --text-b3 | --typo-b3-* | text-b3 | .typo-b3 | 16px |
| B4 | --text-b4 | --typo-b4-* | text-b4 | .typo-b4 | 14px |
| B5 | --text-b5 | --typo-b5-* | text-b5 | .typo-b5 | 13px |
| B6 | --text-b6 | --typo-b6-* | text-b6 | .typo-b6 | 12px |
| C1 | --text-c1 | --typo-c1-* | text-c1 | .typo-c1 | 11px |
| C2 | --text-c2 | --typo-c2-* | text-c2 | .typo-c2 | 10px |
HTML element defaults (tokens.css:336-377)
| Tag | 매핑 | font-weight |
|---|---|---|
<h1> | H1 (32) | 700 |
<h2> | H2 (28) | 700 |
<h3> | H3 (24) | 600 |
<h4> | H4 (22) | 600 |
<h5> | H5 (20) | 600 |
<p> | B3 (16) | (default) |
<code>, <pre> | B5 (13) + --font-mono | (default) |
<body> | 16px · --body-tracking: -0.36px | (default) |
숫자 표기 (Numeric figures)
데이터 숫자는 Inter 기본 폰트로 표기합니다. 자릿수가 세로로 정렬돼야 하는 곳에만 tabular-nums(고정폭 숫자)를 켜고, 그 외 단독 숫자는 기본(비례폭) 그대로 둡니다.
| 상황 | 규칙 | 이유 |
|---|---|---|
| 표의 숫자 열 · 세로로 쌓이는 금액 · 시간 · 시수 | tabular-nums 적용 | 모든 숫자가 같은 폭이라 자릿수 세로선이 맞음 (1도 0과 동일 폭) |
| 단독 인라인 숫자 (이름 옆 사번 1개, 날짜 1개, 카운트 1개) | 적용 안 함 (Inter 기본 비례폭) | 정렬할 상대가 없어 효과가 없고, 오히려 폭이 넓어 보임 |
| 사번 · 코드 등 데이터 식별자 | font-mono 금지 → Inter 사용 | --font-mono(source-code-pro)는 UI 본문(Inter) 사이에서 코드처럼 튐 |
- 적용 방법: Tailwind 기본 유틸
tabular-nums를 그대로 사용합니다. 새 토큰·클래스를 만들지 않습니다 (Tailwind가font-variant-numeric: tabular-nums로 매핑). --font-mono용도: 코드 블록(<code>/<pre>)과 키보드 단축키 표시 전용. 금액·사번·날짜 등 데이터 숫자에는 쓰지 않습니다.
미리보기
모바일 화면 배율 (Mobile font scale)
웹(데스크톱)은 위에서 정의한 타이포 스케일(×1.0)을 기준으로 개발됩니다. 모바일 앱(employee-app)은 같은 화면을 사용자 접근성 배율로 통째로 확대해 보여줍니다 — 폰트만이 아니라 컴포넌트 전체(높이·패딩·아이콘)를 CSS zoom 으로 비례 확대합니다(폰트 토큰만 키우면 글자만 커지고 인풋·헤더 박스는 그대로였기 때문).
- 최초 진입(디폴트)은
기본(×1.2) 입니다. 웹 정의값(×1.0)을 손안의 화면에서 읽기 편하도록 한 단계 키운 배율을 기본으로 줍니다. 즉 웹의 B3 16px 본문은 모바일 기본 배율에서 약 19px로 렌더됩니다. - 사용자는 더보기 → 화면 설정 → 글자 크기에서 세 단계 중 하나를 고릅니다. 선택 즉시 앱 전체가 다시 그려지고,
작게(×1.0)를 뺀 나머지는<html data-font-scale="lg|xl">로 배율이 적용됩니다.
| 단계 | 배율(zoom) | 설명 | 내부 키 · data-font-scale |
|---|---|---|---|
| 작게 | ×1.0 | 웹 타이포 정의값 그대로(무배율) | base · (속성 없음) |
| 기본 | ×1.2 | 디폴트 · 최초 진입값 | lg · data-font-scale="lg" |
| 크게 | ×1.4 | 저시력·고령 사용자 대응 | xl · data-font-scale="xl" |
미리보기 (세 배율 비교)
같은 화면 카드를 세 배율로 나란히 렌더한 것입니다. 라벨(배율)은 고정 크기이고, 카드 안쪽만 실제 zoom 으로 확대됩니다 — 폰이 보여 주는 실제 크기 변화입니다.
구현 위치
- 배율 상태·저장·적용:
apps/employee-app/src/stores/font-scale-store.ts(디폴트lg=기본,base=작게만 무배율) zoom배율 CSS:apps/employee-app/src/styles/main.css(html[data-font-scale="lg|xl"] body { zoom })- 설정 UI:
apps/employee-app/src/views/modals/display-settings.html· 진입점은 더보기 화면
검토 필요 사항
1. 두 토큰 체계 공존 — 병합 불가 (검증 완료)
| 항목 | tokens.css (:root) | design-system.css (@theme) |
|---|---|---|
| 토큰 prefix | --typo-* | --text-* |
| 역할 | HTML 기본 태그 defaults (<h1>,<p>,<code>) — 항상 :root에 출력 | Tailwind 유틸 생성 (text-b5 등) |
| tree-shaking | ❌ 안 됨 (항상 살아있음) | ✅ 됨 — 미사용 등급은 빌드에서 제거 |
| Family 토큰 | --font-inter/poppins/pretendard/mono/app | 동일(@theme) — --ds-font-family는 이제 var(--font-app) 별칭 |
| Body letter-spacing | --body-tracking: -0.36px | (없음 — Tailwind defaults) |
핵심: --text-*는 @theme이라 Tailwind가 실제 사용된 등급만 빌드 :root에 출력합니다 (admin dist 확인: text-b5/text-c2 있음, text-h1 없음). 그래서 <h1> 같은 기본 태그를 var(--text-h1)로 바꾸면 값이 사라져 깨집니다 → --typo-*는 tree-shaking 안 되는 :root 기본값 층으로 반드시 유지. 값(size/lh/tracking)은 두 곳에 중복되지만 메커니즘이 달라 단일화 대상이 아님. (var() 연결도 미사용 등급은 같은 이유로 깨짐.)
값 중복을 정말 없애려면 Tailwind v4
@theme static(전체 토큰 강제 출력)으로 바꿔야 하는데, 출력 CSS가 커지고 동작 검증이 필요한 별도 과제.
2. B1 토큰 빠짐
H5(20px) → B2(18px) 사이의 19px 단계가 비어 있음. 의도된 디자인인지, 추가가 필요한지 확인 필요.
3. font-weight 토큰 미정의
코드 전반에 font-weight: 600 등 숫자가 하드코딩(140+ 건). 시맨틱 토큰 후보:
| 의미 | 값(추정) |
|---|---|
--font-weight-regular | 400 |
--font-weight-medium | 500 |
--font-weight-semibold | 600 |
--font-weight-bold | 700 |
4. 토큰에 없는 사이즈가 실코드에 다수 존재
- 15px: 20건 하드코딩 (토큰 미정의). 14px(B4) 또는 16px(B3)로 흡수할지 결정 필요.
- 9px / 8px / 7px: Tailwind
text-[9px]100건 ·text-[8px]38건 ·text-[7px]2건. C2(10) 아래 단계 토큰 추가 또는 사용 금지.
5. App default 폰트 스택의 Poppins 위치
--font-app 스택에서 Poppins가 InterVariable·Pretendard 다음에 옴 (tokens.css:70). 실제 사용처는 매우 제한적(브랜드 로고/특정 헤드라인). fallback 순위가 의도된 것인지, 또는 별도 토큰으로 빼야 하는지 검토.
토큰 미사용 사용처
토큰이 정의돼 있어도 실제 코드는 대부분 하드코딩입니다. 정리 우선순위가 높은 항목들.
A. font-size: NNpx (CSS·인라인 style)
| 값 | 건수 | 인접 토큰 |
|---|---|---|
13px | 64 (49 + 15 no-space) | --text-b5 / text-b5 |
12px | 53 (43 + 10) | --text-b6 / text-b6 |
14px | 34 (20 + 14) | --text-b4 / text-b4 |
15px | 20 (12 + 8) | 🔴 토큰 없음 → b4(14) 또는 b3(16) 흡수 결정 |
11px | 16 | --text-c1 / text-c1 |
18px | 13 | --text-b2 / text-b2 |
28px | 3 | --text-h2 / text-h2 |
22px | 3 | --text-h4 / text-h4 |
20px | 3 | --text-h5 / text-h5 |
10px | 5 | --text-c2 / text-c2 |
8px | 6 | 🔴 토큰 없음 |
B. Tailwind arbitrary text-[NNpx]
| 값 | 건수 | 인접 토큰 |
|---|---|---|
text-[10px] | 987 | text-c2 |
text-[11px] | 281 | text-c1 |
text-[9px] | 100 | 🔴 토큰 없음 |
text-[8px] | 38 | 🔴 토큰 없음 |
text-[16px] | 9 | text-b3 |
text-[14px] | 8 | text-b4 |
text-[13px] | 5 | text-b5 |
text-[12px] | 6 | text-b6 |
text-[7px] | 2 | 🔴 토큰 없음 |
가장 큰 단일 항목
text-[10px] 987건. 정확히 text-c2로 일괄 치환 가능 — mechanical rename 후보 1순위.
C. font-weight 하드코딩
| 값 | 건수 |
|---|---|
font-weight: 600 | 60 |
font-weight: 500 | 40 |
font-weight: 700 | 25 (20 + 5 no-space) |
font-weight: 400 | 15 |
font-weight: 800 | 3 |
font-weight: 100 | 3 |
→ 시맨틱 weight 토큰 정의 후 일괄 치환 권장.
D. font-family 하드코딩 — 의도된 보존이 대부분
| 위치 | 사용 폰트 | 비고 |
|---|---|---|
packages/api/src/services/email.service.ts:74 | -apple-system, BlinkMacSystemFont, ... | 이메일 (CSS 변수 미지원) — 보존 |
packages/api/src/utils/certificate-template.ts:44 | 'Malgun Gothic', '맑은 고딕', sans-serif | PDF 인쇄용 — 보존 |
packages/api/src/routers/document-template.router.ts:243 | 'Malgun Gothic', ... | 증명서 출력 — 보존 |
apps/admin/src/utils/tinymce.ts:49 | 'Malgun Gothic', ... | TinyMCE 에디터 컨텐츠 — 보존 |
apps/admin/src/app.ts:3119 | 'Malgun Gothic', ... | A4 인쇄 스타일 — 보존 |
packages/test/src/reporter/html-generator.ts | 'Inter', ... 등 | 테스트 리포트 standalone — 보존 |
apps/employee-app/src/styles/main.css:17 | font-family: unset | 🟡 의도 확인 필요 |
apps/admin/src/styles/main.css:1741 | ui-monospace, SFMono-Regular, ... | 🟡 --font-mono 토큰으로 치환 가능 |
사용 우선순위 (코드 작성 시)
1. Tailwind utility — text-h1, text-b3, text-c2
(가장 짧고 빌드 시 정적 분석 가능)
2. .typo-* class — class="typo-h1"
(tokens.css의 수동 정의 utility — 기존 코드 호환용)
3. CSS variable — font-size: var(--text-h1)
font-size: var(--typo-h1-size)
(HTML element default 매핑이나 동적 스타일 시)
4. (지양) 하드코딩 — font-size: 13px
토큰으로 표현 가능하면 토큰 사용목표 & 로드맵
최종 목표
literal 값 중복을 제거(가능한 건 별칭/단일화, 불가한 건 메커니즘 분리 유지)하고, 코드 전반의 size/weight 하드코딩을 토큰 호출로 정리한다.
주의:
--typo-*(:root기본값)와--text-*(@theme유틸)는 Tailwind tree-shaking 때문에 하나로 합칠 수 없음 — 두 체계는 유지하되 값 중복만 줄인다. font-weight 토큰은 이미 신설 완료.
우선순위 작업
| # | 작업 | 상태 |
|---|---|---|
| 1 | @font-face 정의 + 폰트 파일 적재 | ✅ 완료 |
| 2 | Typography scale 정의 (H1~C2 12단계) | ✅ 완료 |
| 3 | HTML element default 매핑 | ✅ 완료 (<h1>~<h5>, <p>, <code>) |
| 4 | 두 토큰 체계(--typo-*, --text-*) 단일화 | ⛔ 불가 — 유지 (tree-shaking으로 메커니즘 분리, #1 참고) |
| 5 | --font-app ≡ --ds-font-family 중복 해소 | ✅ 완료 (--ds-font-family: var(--font-app) 별칭) |
| 6 | B1 토큰(19px) 자리 결정 | 🔴 미정 (디자이너 컨펌 필요) |
| 7 | font-weight 시맨틱 토큰 신설 (regular/medium/semibold/bold) | ✅ 완료 (정의+사용) · 앱 하드코딩 치환은 🔴 미완 |
| 8 | text-[10px] 987건 → text-c2 일괄 치환 | 🔴 mechanical rename 가능 |
| 9 | font-size: NNpx 하드코딩 ~200건 토큰 호출로 정리 | 🔴 보류 |
| 10 | 15px / 8px / 9px / 7px 토큰 결정 (추가 또는 흡수) | 🔴 미정 |
| 11 | 다크 모드용 typography 미세 조정 검토 | 🔴 미정 |
변경 이력
- 2026-07-24 — "모바일 화면 배율(Mobile font scale)" 섹션 신설: 웹은 정의 스케일(×1.0) 기준 개발, employee-app은
zoom으로 전체 비례 확대. 배율 단계 라벨을 작게(×1.0) / 기본(×1.2) / 크게(×1.4) 로 정리하고 디폴트를기본(×1.2) 으로 변경(이전: 기본 1.0 / 크게 1.2 / 매우 크게 1.4, 디폴트 1.0). 세 배율 비교 미리보기 추가. - 2026-06-18 — 폰트 스택 중복 정리:
--ds-font-family를var(--font-app)별칭으로 변경(literal 단일화·값 동기화). 검증으로--typo-*↔--text-*는 tree-shaking 때문에 병합 불가임을 확인 → 문서의 "단일화 대상" 표현을 "메커니즘 분리 유지"로 정정. font-weight 토큰은 이미 정의 완료(문서의 "미정의" 정정). - 2026-06-18 — "숫자 표기(Numeric figures)" 섹션 신설: 표/열엔
tabular-nums, 단독 인라인 숫자엔 미적용, 사번·코드 식별자에font-mono금지(Inter 사용) - (날짜 미상) Typography scale 12단계 +
--typo-*/--text-*두 체계 정의 - (날짜 미상)
tokens.css신설 →design-system.css에서@import합성
전체 토큰 정의: packages/static/styles/tokens.css · design-system.css