Design TokensP2 본문

디자인 토큰

Primitive → Semantic → Component 3계층 토큰의 구조와 규칙, Web/Flutter 소비 방법. 한 곳(JSON SSOT)을 고치면 두 플랫폼이 함께 바뀝니다.

마지막 업데이트 2026-06-12

3계층 구조#

토큰 정본은 tokens/ 디렉토리의 W3C Design Tokens JSON 하나입니다(AD-2). codegen(make tokens)이 CSS 변수와 Dart 상수를 동시에 생성합니다.

계층참조 규칙위반 시
coreliteral만 (alias 금지)빌드 실패
semanticcore만 참조빌드 실패
componentsemantic만 참조 (primitive 직접 참조 금지 — AD-2 #4)빌드 실패

토널 램프 (Primitive 생성)#

core 램프는 손으로 고른 hex가 아니라 톤 수학으로 생성됩니다(ADR-013). 톤 번호는 곧 CIELAB L*(지각 명도, D65) — t40은 모든 hue에서 같은 명도라, 두 색의 대비가 톤 차이만으로 결정됩니다. Material 3의 tonal palette와 같은 정의를 HCT 엔진 없이 scripts/build-tokens/src/tonal.ts(culori lch65)로 구현했습니다.

neutral — 24톤 (표면·상태 레이어 기반)
0
4
6
10
12
17
20
22
24
30
40
50
60
70
80
87
90
92
94
95
96
98
99
100
  • t22다크 surface-raised (tone 수학 파생)
  • t40M3 라이트 전경 기준
  • t80M3 다크 전경 기준

톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.

색 램프는 표준 13톤입니다 — t40(라이트 기준)과 t80(다크 기준)의 대칭이 테마 전환 공식이 됩니다.

blue
0
10
20
30
40
50
60
70
80
90
95
99
100
  • t40라이트 primary
  • t80다크 primary

톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.

green
0
10
20
30
40
50
60
70
80
90
95
99
100

톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.

red
0
10
20
30
40
50
60
70
80
90
95
99
100

톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.

amber
0
10
20
30
40
50
60
70
80
90
95
99
100

톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.

sky
0
10
20
30
40
50
60
70
80
90
95
99
100

톤 번호 = CIELAB L*(지각 명도, D65) — 0 검정 → 100 흰색. 같은 번호는 모든 hue에서 같은 명도라 대비가 톤 차이로 결정됩니다.

램프는 승인된 기존 팔레트의 실측 (L*, C, H) 프로파일을 보간해 생성합니다 — 체계화이지 리베이스가 아닙니다. 빌드 게이트가 앵커 충실도(기존 색을 채널 Δ≤2로 재현)와 톤 대비 법칙(Δtone≥504.4:1, 명시 전경/배경 페어 → 4.5:1)을 매 빌드 검증합니다. 새 브랜드 컬러는 프로파일 한 줄이면 전체 톤·상태 레이어가 자동 파생됩니다.

네이밍#

JSON 경로가 그대로 CSS 변수명과 Dart 상수명이 됩니다.

JSON 경로CSSDart
blue.600--wds-blue-600WizPalette.blue600
color.primary--wds-color-primaryWizColors.light.primary / .dark.primary
font.size.body-1--wds-font-size-body-1WizTypography.sizeBody1
space.4--wds-space-4WizSpacing.s4
button.bg--wds-button-bgWizButtonTokens.light.bg

사용법#

Web — CSS 변수#

alias는 var() 참조로 유지됩니다(테마 전환은 [data-theme]가 처리).

.card {
  background: var(--wds-color-surface);
  border-radius: var(--wds-radius-md);
  padding: var(--wds-space-6);
  box-shadow: var(--wds-shadow-sm);
}

Flutter — 생성 상수#

Dart 타겟은 빌드타임에 평면화됩니다 — rem은 px(×16) double로, shadow는 BoxShadow로, duration은 Duration으로, 이징은 Cubic으로 변환됩니다.

import 'package:wiz_ui/wiz_ui.dart';

Container(
  color: WizColors.light.surface,          // 다크: WizColors.dark.surface
  padding: const EdgeInsets.all(WizSpacing.s6),
  decoration: BoxDecoration(
    borderRadius: BorderRadius.circular(WizRadius.md),
    boxShadow: const [WizShadows.sm],
  ),
)

두 타겟의 일치는 교차 타겟 테스트가 보증합니다 — 모든 시멘틱 컬러의 light/dark computed 값이 CSS와 Dart에서 동일함을 매 빌드 검증.

시멘틱 컬러 전체#

라이트가 정본, 다크는 오버라이드입니다. 상세 설계 근거는 다크 모드 참조.

토큰라이트다크설명

컴포넌트 토큰#

semantic만 참조합니다 — 테마는 참조 경로를 따라 자동 적용됩니다.

토큰설명

변경 절차#

토큰 변경은 영향 등급(Token Impact Matrix)에 따라 차등 승인됩니다 — Primitive 변경은 Governance Board 승인(High), 문서 수정은 Owner 승인(Low). 전체 절차는 MASTER_PLAN §12 참조.

P2 확정 기록#

항목결정근거
Blue 700 표기 모호#1252B2 확정시각 대조 — #125282(라벨)는 램프 hue 연속성 파괴
Warning 표기 모호#F59E0B 확정두 후보 시각 구분 불가 — 업계 표준값 채택
color.linkblue.600 → 700 승격 (의도 변경)600은 모든 라이트 표면에서 4.39:1 — AA 미달
color.on-primary(다크)white → gray.900 반전다크 primary(blue.500) 위 백색은 2.96:1
color.text-placeholder라이트 gray.400→500 / 다크 500→400 (의도 변경)placeholder도 텍스트 — 시드값은 백색 입력면 2.54:1
Button 600+백색 (DD-6)large text 전용 정책4.39:1 ≥ 3:1(large) — 일반 텍스트 버튼은 P3에서 strong 변형