React 프로젝트에서 사용자가 실시간으로 테마 색상을 변경하도록 구현하고 싶으신가요? CSS 변수(:root)와 JavaScript를 결합하면 별도의 CSS 파일을 교체하지 않고도 손쉽게 색상을 바꿀 수 있습니다. 이번 글에서는 기본 설정부터 고급 팁까지 단계별로 살펴보겠습니다.
1. CSS 변수 정의하기
먼저 :root에 테마에 사용할 변수를 선언합니다. src/index.css 혹은 전역 스타일 파일에 아래와 같이 작성합니다.
:root {
--color-primary: #1976d2;
--color-background: #ffffff;
--color-text: #212121;
}
body {
background-color: var(--color-background);
color: var(--color-text);
}
.button {
background-color: var(--color-primary);
color: #fff;
border: none;
padding: 0.5rem 1rem;
cursor: pointer;
}
2. JavaScript로 CSS 변수 업데이트
CSS 변수는 document.documentElement.style.setProperty('--var-name', value) 로 언제든 변경할 수 있습니다. React에서는 이를 훅으로 감싸면 재사용성이 높아집니다.
import { useCallback } from 'react';
export const useTheme = () => {
const setTheme = useCallback((vars) => {
const root = document.documentElement;
Object.entries(vars).forEach(([key, value]) => {
root.style.setProperty(`--${key}`, value);
});
}, []);
return { setTheme };
};
3. 테마 토글 컴포넌트 만들기
이제 위 훅을 사용해 라이트·다크 테마를 전환하는 UI를 구현합니다.
import React, { useState, useEffect } from 'react';
import { useTheme } from './useTheme';
const lightTheme = {
'color-primary': '#1976d2',
'color-background': '#ffffff',
'color-text': '#212121',
};
const darkTheme = {
'color-primary': '#90caf9',
'color-background': '#121212',
'color-text': '#e0e0e0',
};
export default function ThemeToggle() {
const { setTheme } = useTheme();
const [isDark, setIsDark] = useState(false);
useEffect(() => {
setTheme(isDark ? darkTheme : lightTheme);
}, [isDark, setTheme]);
return (
);
}
4. 사용자가 직접 색상 선택하기
단순 토글이 아니라 사용자가 색상 팔레트를 선택하도록 하면 더욱 유연한 커스터마이징이 가능합니다. input[type="color"]와 useTheme을 결합해보세요.
export default function CustomColorPicker() {
const { setTheme } = useTheme();
const [primary, setPrimary] = useState('#1976d2');
const handleChange = (e) => {
const newColor = e.target.value;
setPrimary(newColor);
setTheme({ 'color-primary': newColor });
};
return (
);
}
5. 로컬스토리지에 테마 상태 저장
페이지를 새로고침해도 사용자가 선택한 테마가 유지되게 하려면 로컬스토리지를 활용합니다.
useEffect(() => {
const saved = localStorage.getItem('theme');
if (saved) {
const vars = JSON.parse(saved);
setTheme(vars);
setIsDark(vars['color-background'] === '#121212');
}
}, []);
useEffect(() => {
const current = isDark ? darkTheme : lightTheme;
localStorage.setItem('theme', JSON.stringify(current));
}, [isDark]);
6. 최적화 팁
- CSS 변수는
transition과 결합하면 부드러운 색상 전환 효과를 줄 수 있습니다. 예:body { transition: background-color 0.3s, color 0.3s; } - 대규모 프로젝트에서는 테마 스키마를
typescript인터페이스로 정의해 타입 안전성을 확보하세요. - SSR(Next.js) 환경에서는
useEffect대신useLayoutEffect를 사용해 클라이언트와 서버 간 스타일 불일치를 방지합니다.
위 과정을 따라 하면 React 앱에서 CSS 변수와 JavaScript를 활용한 런타임 테마 커스터마이징을 손쉽게 구현할 수 있습니다. 필요에 따라 색상 외에도 폰트, 간격 등 다양한 디자인 토큰을 변수화하면 더욱 풍부한 사용자 맞춤형 UI를 제공할 수 있습니다.
'React' 카테고리의 다른 글
| React와 Zustand의 미들웨어(Devtools, Persist) 활용법 심화 (0) | 2026.10.01 |
|---|---|
| React 앱에 로컬화된 날짜·시간 포맷팅을 위한 date-fns-tz와 Intl 사용법 (0) | 2026.10.01 |
| React와 Recoil로 비동기 상태 흐름 관리하고 selectorFamily 활용하기 (0) | 2026.09.30 |
| React 프로젝트에서 GitHub Actions를 이용한 자동 배포와 버전 관리 워크플로우 설계 (0) | 2026.09.29 |
| React와 VitePress를 결합해 컴포넌트 문서화 사이트 구축하기 (0) | 2026.09.29 |