--- id: wiki-2026-0508-다크-모드-및-다중-브랜드-테마-동적-전환-시스템 title: 다크 모드 및 다중 브랜드 테마 동적 전환 시스템 category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Dark Mode, Theme Switching, Multi-brand Theming] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [frontend, css, theming, dark-mode, design-system] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: TypeScript/CSS framework: React/Next.js --- # 다크 모드 및 다중 브랜드 테마 동적 전환 시스템 ## 매 한 줄 > **"매 CSS variables × design tokens × runtime swap 의 zero-flash theming"**. 매 다크 모드는 단순 색상 toggle이 아닌, design token system의 multi-channel orchestration. 2026 표준은 `light-dark()` CSS function + `prefers-color-scheme` + system token + brand override 의 4-layer cascade. ## 매 핵심 ### 매 4-Layer Token Architecture 1. **Primitive tokens**: `--color-blue-500: oklch(60% 0.2 240)`. 2. **Semantic tokens**: `--color-bg-primary` (theme-aware). 3. **Component tokens**: `--button-bg = --color-action`. 4. **Brand override**: `[data-brand="acme"] { --color-action: ... }`. ### 매 SSR Flash 방지 - Inline blocking script (head) 의 `localStorage` read → `` 의 set before paint. - Next.js: `next-themes` library 의 표준. - Cookie-based 의 SSR-aware (Next 15 RSC). ### 매 응용 1. GitHub 의 `light/light-high-contrast/dark/dark-dimmed/dark-high-contrast` 의 5 modes. 2. Stripe Dashboard 의 brand switcher (Atlas, Climate 등). 3. Linear 의 theme + accent color picker. 4. VS Code 의 theme marketplace (color-theme JSON). ## 💻 패턴 ### 1. CSS `light-dark()` (2026 baseline) ```css :root { color-scheme: light dark; --bg: light-dark(white, #0a0a0a); --fg: light-dark(#0a0a0a, white); --accent: light-dark(oklch(55% 0.2 250), oklch(70% 0.18 250)); } [data-theme="light"] { color-scheme: light; } [data-theme="dark"] { color-scheme: dark; } ``` ### 2. Multi-brand token override ```css :root[data-brand="default"] { --brand-primary: oklch(55% 0.2 250); } :root[data-brand="acme"] { --brand-primary: oklch(60% 0.22 30); } :root[data-brand="globex"] { --brand-primary: oklch(58% 0.25 140); } .btn-primary { background: var(--brand-primary); color: light-dark(white, black); } ``` ### 3. No-flash inline script (Next.js layout.tsx) ```tsx const themeScript = ` (function() { try { const saved = localStorage.getItem('theme'); const sys = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; const theme = saved || sys; document.documentElement.dataset.theme = theme; document.documentElement.style.colorScheme = theme; } catch (e) {} })(); `; export default function RootLayout({ children }: { children: React.ReactNode }) { return (