stack-analysis
CHAPTER 22 / 90
읽기 약 2분
FUNCTION
디자인 토큰 + CSS 변수: 다크모드의 기반
핵심 개념
design tokens·CSS variables·prefers-color-scheme — 토큰 일원화.
본문
CSS 변수 + 토큰 시스템
/* app/globals.css */
@layer base {
:root {
/* Color Tokens — Light */
--bg-primary: #ffffff;
--bg-secondary: #f9fafb;
--bg-card: #f3f4f6;
--text-primary: #111827;
--text-secondary: #4b5563;
--text-muted: #9ca3af;
--color-primary: #6366f1;
--color-primary-dim: rgba(99,102,241,0.08);
--color-primary-border: rgba(99,102,241,0.2);
--color-border: rgba(0,0,0,0.1);
/* Spacing */
--space-xs: 0.25rem;
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 2rem;
--space-xl: 4rem;
/* Radius */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
/* Shadow */
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.07);
--shadow-lg: 0 10px 25px rgba(0,0,0,0.1);
}
.dark {
--bg-primary: #0a0a0a;
--bg-secondary: #111111;
--bg-card: #1a1a1a;
--text-primary: #f9fafb;
--text-secondary: #d1d5db;
--text-muted: #6b7280;
--color-border: rgba(255,255,255,0.1);
--shadow-sm: 0 1px 2px rgba(0,0,0,0.3);
--shadow-md: 0 4px 6px rgba(0,0,0,0.4);
--shadow-lg: 0 10px 25px rgba(0,0,0,0.5);
}
}ThemeProvider (Next.js)
pnpm add next-themes// app/providers.tsx
'use client';
import { ThemeProvider as NextThemesProvider } from 'next-themes';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<NextThemesProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</NextThemesProvider>
);
}
// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="ko" suppressHydrationWarning>
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}토글 컴포넌트
'use client';
import { useTheme } from 'next-themes';
import { useEffect, useState } from 'react';
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);
if (!mounted) return null;
return (
<button
onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
aria-label="테마 전환"
>
{theme === 'dark' ? '🌙' : '☀️'}
</button>
);
}Storybook 토큰 시각화
// stories/Tokens.stories.tsx
export const Colors = () => {
const tokens = [
{ name: '--bg-primary', usage: '메인 배경' },
{ name: '--text-primary', usage: '본문 텍스트' },
{ name: '--color-primary', usage: '브랜드 강조' },
// ...
];
return (
<table>
<thead>
<tr><th>토큰</th><th>색상</th><th>용도</th></tr>
</thead>
<tbody>
{tokens.map(t => (
<tr key={t.name}>
<td><code>{t.name}</code></td>
<td><div style={{
width: 60, height: 30,
background: `var(${t.name})`,
border: '1px solid #ccc',
}}/></td>
<td>{t.usage}</td>
</tr>
))}
</tbody>
</table>
);
};다음 챕터
CH.23 "반응형 + 컨테이너 쿼리" — 모바일 우선.
AI 프롬프트
🤖 AI에게 잘 물어보는 법 — 모델·전략별 프롬프트
Claude
무료: Sonnet 4.6 / Pro $20/mo: Opus 4.6
내 코드의 디자인 토큰 부분을 분석해서 실전 분석 + 개선 우선순위를 알려줘.
ChatGPT
무료: GPT-5.5 / Plus $20/mo: GPT-5.5 Pro
디자인 토큰 관련 인기 라이브러리/패턴 5개를 비교 분석해서 패턴 추출를 알려줘.
Gemini
무료: 2.5 Flash / Pro $19.99/mo: 3.1 Pro
내 프로젝트 전체에서 디자인 토큰 최적화 가능 위치를 보고해줘.
Grok
무료: Grok 4.1 / SuperGrok $30/mo
2026년 한국 프론트엔드 시장의 디자인 토큰 트렌드를 솔직히 알려줘.
⭐ 이것만 기억하세요
디자인 토큰 + CSS 변수: 다크모드의 기반은 이 3가지만 확실히 잡으세요
1.디자인 토큰 = CSS 변수로 일원화 — light/dark 자동 전환
2.next-themes로 system 우선 + 사용자 선택 저장
3.suppressHydrationWarning + ThemeProvider = SSR 깜빡임 방지
공유하기
진행도 22 / 90