본문 바로가기

프로젝트/잔소리

[잔소리] TailwindCSS 를 이용한 다크모드 구현

반응형

TailwindCSS 를 이용한 다크모드

우선 현 프로젝트는 대시보드 형태로 만들기 때문에, 다크 모드 테마 기능을 지원하여 사용자로 하여금 콘텐츠에 집중할 수 있는 환경을 제공해주는 것이 좋다고 판단하여 추가된 기능입니다. 

 

tailwindCSS 에는 다크모드를 구현하기 위한 예제를 제공해주고 있습니다. 기본이 되는 예제는 다음과 같습니다.

// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  document.documentElement.classList.add('dark')
} else {
  document.documentElement.classList.remove('dark')
}

// Whenever the user explicitly chooses light mode
localStorage.theme = 'light'

// Whenever the user explicitly chooses dark mode
localStorage.theme = 'dark'

// Whenever the user explicitly chooses to respect the OS preference
localStorage.removeItem('theme')

 

위 예제를 참고해서, 다크 모드를 구현해봅니다. 사실 코드 자체가 어려울게 없어서 이런 과정을 거쳐서 만들었구나 참고하는 용도로 보시면 좋을 것 같습니다.

 

루트 레이아웃에서 html className을 dark 로

src/app/layout.tsx 을 보시면 html 태그가 보입니다. 여기에 className의 값으로 dark 를 추가해 줍니다.

// src/app/layout.tsx
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="kr" className='dark'>
      <body className={inter.className}>
        <Header/>
        {children}
        <Footer/>
        </body>
    </html>
  );
}

 

tailwind.config.ts 파일에서 darkMode:'selector' 추가하기

그 다음에는 tailwind.config.ts 파일로 오셔서 darkMode 프로퍼티를 추가하고, 그 값으로 selector 을 추가해줍니다.

import type { Config } from 'tailwindcss';

const config: Config = {
  plugins: [],
  darkMode:'selector' // --> 이렇게 추가해줍니다.
};
export default config;

 

다크 모드 버튼 컴포넌트 추가 및 구현

일단 저의 경우에는 Header 컴포넌트의 header 태그 내에 DarkMode 버튼을 만들어서 사용하고 있습니다. 따라서 DarkMode.tsx 파일을 만들어서 다크 모드 기능을 구현해주었습니다.

 

아래는 현재 작성된 컴포넌트 코드이고, 앞서 예제에서 언급했던 다크모드 코드 예시를 기반으로 사용하기 좋은 형태로 바꿔주었습니다.  window.matchMedia('(prefers-color-scheme: dark)').matches 를 통해 브라우저 자체의 시스템 테마가 다크 모드인지 아닌지를 고려해서 사용자가 테마를 변경할 수 있도록 해주고 있는 코드입니다.

'use client'
export default function DarkMode() {

    function toggleDarkMode() {
        if (localStorage.theme === 'dark'
            || (!('theme' in localStorage)
                && window.matchMedia('(prefers-color-scheme: dark)').matches)) {

            localStorage.setItem('theme', 'light');
            document.documentElement.classList.add('dark');
        } else {
            localStorage.setItem('theme', 'dark');
            document.documentElement.classList.remove('dark');
        }
    }

    return (
        <button onClick={toggleDarkMode} className="dark:text-white">
            다크모드
        </button>
    )
}

 

이제 버튼을 클릭하면 localStorage 에 저장된 theme 키에 해당하는 값이 dark 이냐  light 냐에 따라서 html 태그의 class에 부여된 dark 가 제거되거나 추가되거나 하게 됩니다.

 

 

[참고] 복잡한 코드는 없지만 중요한 포인트

코드 자체는 복잡한게 없지만, 한 가지 중요한 부분이 있습니다. mathMedia 부분 인데, 이 부분은 tailwindcss 에서 제공하는 것이 아니라 브라우저 자체에서 제공하는 기능입니다. 

 

아무 브라우저의 개발자 콘솔을 여신 후 window.mathMedia ~ 입력하시면 아래와 같이 MediaQueryList 라는 생성자 함수가 뜨는 것을 볼 수 있습니다. 이는 주어진 미디어 쿼리에 대한 분석 정보를 저장하고 있는 객체로서 브라우저가 기본적으로 지원하는 다크모드 (즉, 시스템 테마 라고 하죠)에 대한 설정 정보나 @media 등으로 우리가 CSS를 이용해 반응형 레이아웃을 지정하는 쿼리 정보도 제공해줍니다. 

 

 

이는 공신력 있는 문서인 MDN 사이트( https://developer.mozilla.org/ko/docs/Web/API/Window/matchMedia )에서도  설명하고 있는 메서드이므로 꼭 한 번 읽어보시길 바랍니다. 요새는 GPT, claude, 제미니, 코파일럿 등에서 쉽게 예시 등을 확인할 수 있으니 크게 어려울 것은 없습니다.

 

 

Header 컴포넌트에 DarkMode 컴포넌트 넣기

앞서 만들어진 컴포넌트를 Header 컴포넌트로 가져와서 배치해줍니다. 

import Link from "next/link";
import DarkMode from "./DarkMode";

export default function Header() {
    return (
        <header className="w-full h-[50px]  flex items-center border-b-[1px] dark:bg-[#212125] dark:border-gray-700  ">
            <Link href="" className="w-[100px] flex items-center  p-[3px] mx-4">
                <img
                    className="rounded-full"
                    width={24}
                    height={24}
                    src="icons/android-launchericon-48-48.png"
                    alt="사이트 로고" />
                <h1 className="dark:text-[white] px-[5px]">잔소리</h1>
            </Link>
            <DarkMode/>
        </header>
    )
}

 

 

 

 

결과 보기

다크 모드를 적용하고 실제 결과를 살펴봅시다. 

 

 

참고로 localStorage 를 살펴보시면 theme 가 dark 일 때와 light 일 때가 변경되는 것을 볼 수 있습니다. 브라우저 상태로 캐싱되어 있기 때문에 새로고침해도 테마를 유지할 수 있게 됩니다.

 

정리

Tailwindcss 를 이용해서 간단한 다크 모드를 구현해 보았습니다. 코드 설명 이런거는 솔직히 요즘 세상에는 큰 의미가 없는 것 같아서 어떤 방향으로 작성했다 라는 것을 보여주는? 그런 느낌으로 작성해보았습니다. 확실히 다크모드가 있으니, 눈이 약간은 더 편해지네요. 이건 개발할 때도 눈 보호되고 좋은 것 같습니다.

 

현재는 미완성된 UI와 디자인이라서 투박하지만 향후 콘텐츠가 더 추가되고, 정밀해지면 빛을 발하리라 봅니다. 

 

 

반응형