React · 2026-04-05

React로 다크 모드 구현과 테마 스위칭 전략

React 프로젝트에서 CSS 변수 기반 테마를 적용하고, 로컬 저장소와 브라우저 선호도를 결합한 테마 스위칭 구현 예제

작성일 : 2026-04-05 ㆍ 작성자 : 관리자
post
목차

개요

다크 모드는 사용자 경험을 개선하는 중요한 기능이다. 구현 방식에 따라 성능, 접근성, 유지보수성이 달라진다. 이 글은 CSS 변수와 React를 결합한 실용적 전략을 설명한다. 처음 접하는 개발자도 이해할 수 있도록 단계별로 정리된다.

전략 요약

  • CSS 변수로 색상 테마를 분리한다.
  • 루트 엘리먼트에 데이터 속성(data-theme)을 사용해 테마를 전환한다.
  • 사용자 설정은 localStorage에 저장한다.
  • 브라우저의 prefers-color-scheme을 초기값으로 활용한다.
  • FOUC(초기 깜박임)를 막기 위한 초기 스크립트를 적용한다.

왜 CSS 변수인가

CSS 변수는 런타임에 값 변경이 가능하다. 변수 중심 설계는 컴포넌트 스타일을 건드리지 않고 테마를 변경할 수 있게 한다. 또한 트랜지션 적용이 쉬워 부드러운 전환을 제공한다.

기본 CSS 구조

루트에 기본 변수를 선언하고 다크 테마용 변수는 data-theme 속성으로 분리한다. 핵심 색상만 변수로 관리하면 유지보수가 용이하다.

:root {
  --bg: #ffffff;
  --text: #111827;
  --primary: #2563eb;
}

html[data-theme="dark"] {
  --bg: #0b1220;
  --text: #e6eef8;
  --primary: #60a5fa;
}

body {
  background-color: var(--bg);
  color: var(--text);
  transition: background-color 200ms ease, color 200ms ease;
}

React에서 테마 상태 관리

간단한 훅으로 테마 상태와 토글 함수를 만든다. 초기값은 localStorage, 없으면 prefers-color-scheme, 그 다음 기본값 순으로 결정한다.

import { useEffect, useState } from 'react'

function useTheme() {
  const [theme, setTheme] = useState(() => {
    try {
      const stored = localStorage.getItem('theme')
      if (stored) return stored
    } catch (e) {}
    const prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches
    return prefersDark ? 'dark' : 'light'
  })

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme)
    try { localStorage.setItem('theme', theme) } catch (e) {}
  }, [theme])

  const toggle = () => setTheme(prev => (prev === 'dark' ? 'light' : 'dark'))

  return { theme, toggle }
}

export default useTheme

토글 컴포넌트 예제

단순한 버튼으로 구현하면 접근성 확보가 필요하다. aria-pressed 속성을 사용해 상태를 알린다.

import React from 'react'
import useTheme from './useTheme'

function ThemeToggle() {
  const { theme, toggle } = useTheme()

  return (
    <button onClick={toggle} aria-pressed={theme === 'dark'}>
      {theme === 'dark' ? '라이트 모드' : '다크 모드'}
    </button>
  )
}

export default ThemeToggle

초기 깜박임(FOUC) 방지

서버 사이드 렌더링이나 정적 페이지에서 클라이언트가 로드될 때 잠깐 동안 잘못된 테마가 보일 수 있다. 이를 막기 위해 인라인 스크립트로 초기 테마를 즉시 적용한다.

(function() {
  try {
    var stored = localStorage.getItem('theme')
    if (stored) {
      document.documentElement.setAttribute('data-theme', stored)
      return
    }
    var mql = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)')
    if (mql && mql.matches) document.documentElement.setAttribute('data-theme', 'dark')
  } catch (e) {}
})();

추가 고려사항

  • 컴포넌트 수준 스타일에는 CSS 변수 사용을 권장한다.
  • 이미지나 SVG는 필터나 변수를 이용해 적응시키는 방법을 검토한다.
  • 접근성 측면에서 색 대비를 확인한다.
  • 서버 사이드 렌더링 환경에서는 초기 HTML에 데이터 속성 삽입을 고려한다.

맺음말

react 다크 모드 구현은 CSS 변수 중심 설계와 작은 초기 스크립트로 깔끔하게 해결된다. 테마 토글 react 구현 시 user preference와 persistence를 결합하면 사용자 경험이 개선된다. 이 패턴은 확장성이 높아 다양한 프로젝트에서 재사용 가능하다.

react 다크 모드 구현 테마 토글 react css 변수 테마 적용 react 다크 모드 prefers-color-scheme localStorage 테마 웹 접근성 테마 스위칭 전략