1. 디자인 토큰이란?
디자인 토큰(Design Token)은 색상·간격·타이포그래피·그림자 등 UI의 시각적 결정을 이름이 붙은 변수로 추상화한 것입니다. 단순히 #C96442를 기억하는 것이 아니라, 그것이 브랜드 포인트 컬러라는 의미를 코드에 담는 일입니다.
디자인 시스템이 없는 프로젝트에서는 같은 오렌지색이
#C96442, #c96442, rgb(201,100,66)로 분산됩니다. 토큰은 이 혼란을 단 하나의 진실로 수렴시킵니다.
| 방식 | 예시 | 문제점 |
|---|---|---|
| 하드코딩 | color: #C96442 | 변경 시 전체 파일 검색·교체 필요 |
| SCSS 변수 | color: $brand-orange | JS에서 접근 불가, 런타임 변경 어려움 |
| CSS 변수 | color: var(--color-brand) | 타입 없음, 오타 감지 어려움 |
| 디자인 토큰 | $color-brand-primary + CSS var | 두 방식의 장점 결합 |
2. 색상 시스템 3계층 설계
견고한 색상 시스템은 원시(Primitive) → 시맨틱(Semantic) → 컴포넌트(Component) 3계층으로 구성됩니다.
// ── 계층 1: Primitive (원시값 — 팔레트 전체 정의) ── $palette-orange-100: #FFF7ED; $palette-orange-300: #FED7AA; $palette-orange-500: #C96442; // 주 브랜드 컬러 $palette-orange-700: #9A4A2E; $palette-orange-900: #6B2E18; $palette-neutral-50: #FAFAF8; $palette-neutral-100: #F5F0E8; $palette-neutral-200: #E8DDD4; $palette-neutral-900: #1C1C1C; // ── 계층 2: Semantic (의미 — 역할 기반 이름) ── $color-brand-primary: $palette-orange-500; // 주 포인트 $color-brand-secondary: $palette-orange-300; // 보조 포인트 $color-bg-base: $palette-neutral-50; // 페이지 배경 $color-bg-surface: #FFFFFF; // 카드 배경 $color-bg-muted: $palette-neutral-100; // 섹션 배경 $color-text-default: $palette-neutral-900; // 기본 텍스트 $color-text-muted: #8B6355; // 보조 텍스트 $color-border: $palette-neutral-200; // 경계선 // ── 계층 3: Component (컴포넌트별 별칭) ── $btn-primary-bg: $color-brand-primary; $btn-primary-hover: $palette-orange-700; $card-bg: $color-bg-surface; $card-border: $color-border;
계층을 분리하면 "오렌지를 코랄로 교체해달라"는 요청이 왔을 때 $palette-orange-500 한 줄만 바꿔도 전체 UI가 일관되게 변경됩니다.
3. 시맨틱 컬러 네이밍
이름에 색상 자체를 담으면 안 됩니다. $color-red가 오렌지로 바뀌었을 때 이름이 거짓말을 하게 됩니다. 대신 역할을 이름으로 사용하세요.
| 나쁜 이름 | 좋은 이름 | 이유 |
|---|---|---|
$orange | $color-brand-primary | 브랜드 포인트 역할 표현 |
$light-gray | $color-bg-muted | UI 배경 역할 표현 |
$dark-text | $color-text-default | 텍스트 기본값 역할 표현 |
$red | $color-status-error | 에러 상태 의미 표현 |
추천 카테고리 분류:
$color-brand-*— 브랜드 아이덴티티 색상$color-bg-*— 배경 계열 (base, surface, muted, overlay)$color-text-*— 텍스트 계열 (default, muted, inverse, link)$color-border-*— 경계선 계열 (default, focus, strong)$color-status-*— 상태 계열 (success, warning, error, info)
4. SCSS 변수로 구현하기
SCSS 변수와 CSS 커스텀 프로퍼티를 함께 사용하면 정적 빌드 타임 안전성과 런타임 유연성을 모두 얻을 수 있습니다.
// _tokens.scss — 토큰 단일 진실 원천
:root {
// Primitive
--palette-orange-500: #C96442;
--palette-neutral-50: #FAFAF8;
// Semantic (SCSS → CSS var 브릿지)
--color-brand-primary: var(--palette-orange-500);
--color-bg-base: var(--palette-neutral-50);
--color-text-default: #1C1C1C;
--color-border: #E8DDD4;
}
// _variables.scss — SCSS 변수에 CSS var 연결
$color-brand-primary: var(--color-brand-primary);
$color-bg-base: var(--color-bg-base);
$color-text-default: var(--color-text-default);
$color-border: var(--color-border);
// 컴포넌트에서 사용
.btn-primary {
background: $color-brand-primary; // → var(--color-brand-primary)
color: #fff;
border: none;
}
이 구조에서 브랜드 색상을 변경하려면 --palette-orange-500 한 줄만 수정하면 됩니다. JS에서도 document.documentElement.style.setProperty('--palette-orange-500', '#005FCC')로 런타임 테마 전환이 가능합니다.
5. 다크 모드 확장 전략
토큰 기반 시스템의 진가는 다크 모드 구현에서 드러납니다. 컴포넌트 수정 없이 :root 값만 교체하면 됩니다.
// 라이트 모드 (기본)
:root {
--color-bg-base: #FAFAF8;
--color-bg-surface: #FFFFFF;
--color-text-default: #1C1C1C;
--color-text-muted: #8B6355;
--color-border: #E8DDD4;
}
// 다크 모드 — 오버라이드만!
@media (prefers-color-scheme: dark) {
:root {
--color-bg-base: #0D0D0D;
--color-bg-surface: #181818;
--color-text-default: #F0EDE8;
--color-text-muted: rgba(255,255,255,.45);
--color-border: rgba(255,255,255,.08);
// $color-brand-primary는 그대로 유지 (브랜드 색상 불변)
}
}
// 또는 수동 토글 (.dark-theme 클래스)
.dark-theme {
--color-bg-base: #0D0D0D;
--color-bg-surface: #181818;
--color-text-default: #F0EDE8;
}
브랜드 색상(
--color-brand-primary)은 다크 모드에서 바꾸지 않는 것이 일반적입니다. 배경·텍스트·경계선만 반전시키면 아이덴티티는 유지되면서 가독성이 개선됩니다.