🧩 Design System6. Theming (다크·브랜드·a11y)📖 개요

06 — Theming (Dark Mode · Multi-Brand · Contextual Tokens)

이 문서가 답하는 질문: 디자인 시스템에서 “테마”란 정확히 무엇을 바꾸는 것인가? 다크모드, 멀티 브랜드, RTL, prefers-reduced-motion — 이 다섯 가지는 같은 메커니즘으로 풀 수 있는가, 아니면 각자 다른 도구가 필요한가? 한 줄 답 (Pyramid Top): 테마는 “컴포넌트 코드를 한 줄도 바꾸지 않고 semantic 토큰만 swap하는 컨텍스트” 다 — primitive 토큰(blue.500)은 절대 변하지 않고, semantic 토큰(color.bg.surface)이 라이트/다크/브랜드에서 다른 primitive를 가리킨다. CSS variables + [data-theme] selector가 사실상 표준이고, Tailwind v4의 @theme와 Panda의 conditions가 이 패턴을 1급 시민으로 끌어올렸다.


이 챕터의 위치

01-tokens토큰의 형식(DTCG, 3-tier 계층), 02-color-system색의 수학(OKLCH, 12-step)을 다뤘다면, 이 챕터는 “같은 컴포넌트가 언제 어느 토큰 값을 쓸 것인가” 를 다룬다.

컨텍스트신호(signal)바뀌는 토큰바뀌지 않는 것
다크모드prefers-color-scheme: dark / [data-theme="dark"]color.bg.*, color.fg.*, color.border.*spacing, radius, font-size
멀티 브랜드[data-brand="admin"] vs [data-brand="storefront"]color.accent.*, font.family.brand레이아웃, 컴포넌트 구조
RTLdir="rtl"(대부분 토큰은 그대로)logical properties가 자동 처리
고대비prefers-contrast: more, forced-colors: activecolor.fg.*, color.border.*레이아웃
감속 모션prefers-reduced-motion: reduceduration.*, transition.*색·spacing

핵심 통찰 한 줄: 컴포넌트 토큰(button.bg)을 분기하지 말고, semantic 토큰(color.bg.accent)에서만 분기하라. 100개 컴포넌트가 깨질지, 토큰 한 줄로 끝날지의 차이.


챕터 지도 (Mermaid)


챕터 인덱스

#파일다루는 것핵심 키워드
0101-theme-as-context테마 = “토큰 값을 바꾸는 컨텍스트”. semantic만 분기, component 토큰은 그대로3-tier, semantic, swap point
0202-dark-mode-strategyprefers-color-scheme vs [data-theme] vs .dark, FOUC, color-scheme propertydata-theme, blocking script, color-scheme
0303-multi-brand-systemsAtlassian의 product brands, Shopify의 admin/storefront, 하나의 컴포넌트 라이브러리 + 여러 brand 토큰data-brand, brand scope, primitive 공유
0404-runtime-vs-buildtime-themingCSS vars 런타임 swap vs Tailwind v3 class 빌드, Tailwind v4 @themeruntime, buildtime, CSS bloat
0505-panda-tailwind-theme-configPanda conditions, Tailwind darkMode: 'class', 둘 다 작동하는 패턴_dark, darkMode, custom condition
0606-rtl-and-localizationRTL 지원, logical properties, locale-specific font stackmargin-inline-start, dir, CJK font
0707-system-preferencesprefers-reduced-motion, prefers-contrast, forced-colors (WHCM)a11y, Canvas, CanvasText

핵심 원칙 (5개)

  1. 분기는 semantic 층에서만button.bg를 다크에서 분기하지 말고 color.bg.accent 한 곳에서만.
  2. CSS variables가 런타임 테마의 1급 시민 — Tailwind v3 class swap은 CSS 크기 2배의 함정.
  3. FOUC는 SSR의 약점, blocking <script>로 막는다<html> 렌더 전에 data-theme 설정.
  4. color-scheme property를 잊지 말 것 — 스크롤바, form control도 다크로 가도록.
  5. forced-colors(Windows High Contrast)는 토큰을 무시한다 — system color (Canvas, CanvasText)에 의지하라.

What-if — 이 챕터의 한계

  • 테마 전환 UX (토글 버튼 디자인, 애니메이션)는 04-recipes-variants 또는 컴포넌트 카탈로그 영역.
  • i18n 텍스트 번역은 다루지 않는다 — 토큰화 가능한 시각 자산(font stack, direction)만.
  • Figma Variables의 modes UI 조작법은 08-pipeline-distribution에서.

요약

  • 테마 = semantic 토큰을 swap하는 컨텍스트 — primitive와 component 토큰은 변하지 않는다.
  • 다크모드, 멀티 브랜드, RTL, system preferences는 모두 같은 메커니즘(CSS variables + selector)으로 풀린다.
  • Tailwind v4의 @theme와 Panda의 conditions가 이 메커니즘을 1급 시민으로 끌어올렸다.