본문 바로가기

프론트엔드

1분만에 Nextjs에서 다크모드 구현하기 (next-themes + tailwindCSS)

Nextjs에서 다크모드 구현하기

본 블로그는 next-themes(next-themes) + tailwindCSS를 사용하여 다크모드가 구현되어 있고, 그 방법이 매우 간편하여 소개하고자 한다.

next-themes

next-thems설치

$ npm install next-themes
 or
$ yarn add next-themes

next-themes 사용

  • Nextjs의 layout 파일에서 'use client'를 사용하고 있을 경우, 공식문서 그대로 컴포넌트를 ThemeProvider로 감싸주면 된다.
// layout.tsx
import { ThemeProvider } from 'next-themes'

function MyApp({ Component, pageProps }) {
  return (
    <ThemeProvider>
      <Component {...pageProps} />
    </ThemeProvider>
  )
}

export default MyApp
  • 만약 layout 파일이 csr이 아닐 경우, csr파일을 하나 만들어서 layout파일에서 사용한다.
// Provider.tsx
"use client"
import { ThemeProvider } from "next-themes"

const Providers = ({ children }: { children: React.ReactNode }) => {
    return (
        <ThemeProvider enableSystem={true} attribute="class">
            {children}
        </ThemeProvider>
    )
}

export default Providers
  • enableSystem 을 true로 설정하면 사용자 시스템 설정에 따라 theme이 설정된다.
  • tailwndCSS의 클래스로 다크모드를 설정하기 위해, attribute는 "class"로 했다.
// layout.tsx
import Providers from './Provider'

...

export default async function RootLayout({children,}: { children: React.ReactNode }) {
  const session = await getServerSession(authOptions);

  return (
    <html lang="en">
      <body className={notoSansKr.className}>
        <Providers>
            ...layout 코드
            {children}
        </Providers>
      </body>
    </html>
  )
}

tailwindCSS 설정

  • tailwind.config 파일에서 토글버튼을 사용하여 수동으로 테마 전환을 하기 위해 darkMode를 'class' 로 설정해준다.
// tailwind.config.js

module.exports = {
  darkMode: 'class',
  // ...
}

다크모드 토글 버튼 만들기

  • useTheme() Hook을 사용하여 테마 정보를 가져온다.
    • systemTheme: 시스템 테마, theme: 현재 테마, setTheme: 테마 상태 변경
  • currentTheme을 따로두고 사용하는 이유는, 시스템 테마와 현재 테마가 다를 수 있기 때문이다.
    • 최초설정을 시스템테마로 하였을 경우 theme(현재 테마)은 'light'나 'dark'가 아닌 'system'으로 되기 때문에, theme === 'dark' ? : 와 같이 분기처리하여 화면을 구현할 경우, 원하지 않는 결과가 나올 수 있기 때문이다.
"use client"
import { useTheme } from "next-themes"

export default function DarkModeBtn() {
    const { systemTheme, theme, setTheme } = useTheme()
    const currentTheme = theme === "system" ? systemTheme : theme


    return (
        <div>
            <button 
                className="bg-pink-100 dark:bg-white flex items-center transition duration-300 focus:outline-none shadow"
                onClick={() => {
                    setTheme( currentTheme === 'dark' ? 'light' : 'dark')
                }}
            >
                {
                    currentTheme === 'dark' ? 
                        <div>
                           ...다크모드 버튼
                        </div>   
                    :
                        <div
                           ...라이트모드 버튼
                        </div>  
                }
            </button>
        </div>
    )
}

다크모드 디자인 적용

tailwindCSS 공식 문서에서 나오 듯,

그냥 className에 'dark: ~~' 만 넣어주면, 다크모드에서의 디자인을 추가할 수 있다!

<nav className='bg-white dark:bg-gray-800 flex ...'>