Skip to content

타이포그래피

진행 중 (Typography — work in progress)

  • 폰트 패밀리·문자 스케일 토큰은 정의돼 있으나 실제 코드는 대부분 하드코딩(예: font-size: 13px 64건 — 공백 없는 표기 포함)으로 토큰을 거치지 않습니다.
  • 두 가지 토큰 체계가 공존합니다 (--typo-* in tokens.css vs --text-* in design-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/에 위치합니다.

TokenFamily로드된 파일Weight
--font-interInterVariablefonts/Inter/InterVariable.woff2 (+Italic)100–900 (variable)
--font-poppinsPoppinsPoppins-Regular/Medium/SemiBold/Bold.woff2400 · 500 · 600 · 700
--font-pretendardPretendard Variablefonts/Pretendard/PretendardVariable.woff2100–900 (variable)
--font-monosource-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 규칙을 따릅니다.

미리보기

H1 · 32px / 1.4 / −0.32 · 가나다 Aa
H2 · 28px / 1.4 / −0.28 · 가나다 Aa
H3 · 24px / 1.4 / −0.24 · 가나다 Aa
H4 · 22px / 1.4 / −0.22 · 가나다 Aa
H5 · 20px / 1.4 / −0.2 · 가나다 Aa
B2 · 18px / 1.4 / −0.18 · 가나다 Aa
B3 · 16px / 1.4 / −0.16 · 가나다 Aa (HTML 기본 body)
B4 · 14px / 1.4 / −0.14 · 가나다 Aa
B5 · 13px / 1.4 / −0.13 · 가나다 Aa
B6 · 12px / 1.4 / −0.12 · 가나다 Aa
C1 · 11px / 1.4 / −0.11 · 가나다 Aa
C2 · 10px / 1.4 / −0.1 · 가나다 Aa

토큰 표

등급--text-* (design-system.css)--typo-* (tokens.css)Tailwind utility.typo-* class크기
H1--text-h1--typo-h1-size/-tracking/-lhtext-h1.typo-h132px
H2--text-h2--typo-h2-*text-h2.typo-h228px
H3--text-h3--typo-h3-*text-h3.typo-h324px
H4--text-h4--typo-h4-*text-h4.typo-h422px
H5--text-h5--typo-h5-*text-h5.typo-h520px
B1(없음)(없음)(검토 필요)
B2--text-b2--typo-b2-*text-b2.typo-b218px
B3--text-b3--typo-b3-*text-b3.typo-b316px
B4--text-b4--typo-b4-*text-b4.typo-b414px
B5--text-b5--typo-b5-*text-b5.typo-b513px
B6--text-b6--typo-b6-*text-b6.typo-b612px
C1--text-c1--typo-c1-*text-c1.typo-c111px
C2--text-c2--typo-c2-*text-c2.typo-c210px

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 적용모든 숫자가 같은 폭이라 자릿수 세로선이 맞음 (10과 동일 폭)
단독 인라인 숫자 (이름 옆 사번 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>)과 키보드 단축키 표시 전용. 금액·사번·날짜 등 데이터 숫자에는 쓰지 않습니다.

미리보기

tabular-nums · 1,111 / 2,000 / 88,888 — 자릿수 정렬됨
기본(비례폭) · 1,111 / 2,000 / 88,888 — Inter 기본

모바일 화면 배율 (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 으로 확대됩니다 — 폰이 보여 주는 실제 크기 변화입니다.

작게 · ×1.0
연차 신청
가나다라마 ABCabc
잔여 연차 12.5일 · 12,345원
기본 · ×1.2 · 디폴트
연차 신청
가나다라마 ABCabc
잔여 연차 12.5일 · 12,345원
크게 · ×1.4
연차 신청
가나다라마 ABCabc
잔여 연차 12.5일 · 12,345원

구현 위치

검토 필요 사항

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-regular400
--font-weight-medium500
--font-weight-semibold600
--font-weight-bold700

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)

건수인접 토큰
13px64 (49 + 15 no-space)--text-b5 / text-b5
12px53 (43 + 10)--text-b6 / text-b6
14px34 (20 + 14)--text-b4 / text-b4
15px20 (12 + 8)🔴 토큰 없음 → b4(14) 또는 b3(16) 흡수 결정
11px16--text-c1 / text-c1
18px13--text-b2 / text-b2
28px3--text-h2 / text-h2
22px3--text-h4 / text-h4
20px3--text-h5 / text-h5
10px5--text-c2 / text-c2
8px6🔴 토큰 없음

B. Tailwind arbitrary text-[NNpx]

건수인접 토큰
text-[10px]987text-c2
text-[11px]281text-c1
text-[9px]100🔴 토큰 없음
text-[8px]38🔴 토큰 없음
text-[16px]9text-b3
text-[14px]8text-b4
text-[13px]5text-b5
text-[12px]6text-b6
text-[7px]2🔴 토큰 없음

가장 큰 단일 항목

text-[10px] 987건. 정확히 text-c2로 일괄 치환 가능 — mechanical rename 후보 1순위.

C. font-weight 하드코딩

건수
font-weight: 60060
font-weight: 50040
font-weight: 70025 (20 + 5 no-space)
font-weight: 40015
font-weight: 8003
font-weight: 1003

→ 시맨틱 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-serifPDF 인쇄용 — 보존
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:17font-family: unset🟡 의도 확인 필요
apps/admin/src/styles/main.css:1741ui-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 정의 + 폰트 파일 적재✅ 완료
2Typography scale 정의 (H1~C2 12단계)✅ 완료
3HTML element default 매핑✅ 완료 (<h1>~<h5>, <p>, <code>)
4두 토큰 체계(--typo-*, --text-*) 단일화불가 — 유지 (tree-shaking으로 메커니즘 분리, #1 참고)
5--font-app--ds-font-family 중복 해소완료 (--ds-font-family: var(--font-app) 별칭)
6B1 토큰(19px) 자리 결정🔴 미정 (디자이너 컨펌 필요)
7font-weight 시맨틱 토큰 신설 (regular/medium/semibold/bold)완료 (정의+사용) · 앱 하드코딩 치환은 🔴 미완
8text-[10px] 987건 → text-c2 일괄 치환🔴 mechanical rename 가능
9font-size: NNpx 하드코딩 ~200건 토큰 호출로 정리🔴 보류
1015px / 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-familyvar(--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