본문 바로가기
Project/기타

Next.js 14 다크모드 구현하기 / 웹 이력서(작성 중)

by 이의찬 2024. 4. 2.

0. TL;DR

  • 웹 이력서에 다크모드를 적용할 필요성을 느낌
  • 일관적인 경험을 위해 system값을 기본값으로 사용하고, 이후에는 dark / light모드를 토글로 변환하도록 결정
  • 'system 값 사용'과 'load 시 flickering 이슈' 해결에 장점이 있는 next-themes 라이브러리를 사용해서 구현

1. Why?

이력서의 경우 많은 사람들에게 피드백을 받아보는 것이 좋다고 생각한다. 그래서 어느정도 완성된 이력서 사이트를 친구에게 보여줬더니 개발자를 위한 다크모드는 없냐고 불평을 했다.

개발자의 필수소양,,,

난 사실 화이트모드를 더 좋아하지만, 상당수의 개발자들이 다크모드를 선호하는 것은 사실이다. 내 이력서 보는 사람들도 어두운 화면을 보다가 갑자기 밝은 화면을 보면 불쾌할 수도 있고, 눈 아프다고 그냥 끄고 나가버릴 수도 있으니 다크모드를 구현해보자.


2. How?

아래 두 부분에서 어떻게 구현할지 고민했다.

  1. System 설정 사용
    1. System 설정을 고려한다면, 버튼은 어떻게?
  2. 구현 방법

1. System 설정 사용

구현하는 이유 자체가 사용자의 일관적인 경험을 위해서이니, system 설정에 따라서 다크모드를 해주는 것이 이상적

1-1. System 설정을 고려한다면, 버튼은 어떻게?

Tailwind CSS 공식 페이지의 화면 설정

  • 내 타겟은 면접관, 이 사람들 볼 거 많은데 최대한 덜 귀찮게 하는게 중요
  • 만약 모바일로 들어온다면, 더욱 직관적인게 중요
  • system 설정 넣었다고 굳이 1단계의 depth를 추가하는 것 보다는 그냥 직관적으로 동작하게끔 하고싶음

2. 어떻게 구현할까?

  • 'system 값 사용'과 'load 시 flickering 이슈' 해결에 장점이 있는 next-themes 라이브러리를 사용해서 구현

3. 코드

1️⃣ ThemeProvider를 구현


next-themes를 사용해 ThemeProvider를 구현

  • 'use client'를 통해 client component로 사용하고자 분리
// components/provider/ThemeProvider.tsx

import { ThemeProvider as NextThemesProvider } from 'next-themes';
import { type ThemeProviderProps } from 'next-themes/dist/types';

export default function ThemeProvider({ children }: ThemeProviderProps) {
  return (
    <NextThemesProvider attribute="class" defaultTheme="system">
    // 일관적인 UX를 위해 defaultTheme를 system으로 설정
      {children} 
    </NextThemesProvider>
  );
}

 

  • provider를 Home 컴포넌트에 적용
// ./src/app/mocks/browser.ts

import ThemeProvider from './components/provider/ThemeProvider';

export default function Home() {
  return (
    <ThemeProvider enableSystem> 
      // system의 값을 가져오도록 enableSystem을 true로 설정 
      // ...
     </ThemeProvider>
  • ThemeButton 컴포넌트 구현
// component/app/ThemeButton.tsx

export default function ThemeButton() {
  const [mounted, setMounted] = useState(false);
  const { systemTheme, theme, setTheme } = useTheme();
  const currentTheme = theme === 'system' ? systemTheme : theme;
  // theme값이 'system'이라면 systemTheme값을 가져와서 사용하도록 설정

  const themeChange = (nowTheme: string | undefined) => {
    if (nowTheme === 'dark') {
      return 'light';
    }
    return 'dark';
  };

  const themeButtonHandler = () => {
    setTheme(themeChange(currentTheme));
  };
  
  useEffect(() => {
    setMounted(true);
  }, []);
  // 클라이언트 사이드에서만 접근 가능하도록

  if (!mounted) return null;

// ...

위와 같이 구현한 결과, dark/light 모드 변환이 정상적으로 동작하는 것을 확인

https://resume-legitgoons.vercel.app

 

가치를 만드는 FE 개발자 이의찬입니다

신입 프론트엔드 개발자 이의찬의 웹 이력서 사이트입니다.

web-portfolio-legitgoons.vercel.app


4. 래퍼런스

https://www.d5br5.dev/blog/nextjs_blog/theme

 

Next.js Dark Mode 적용하기 | D5BL5G

Next.js, tailwind 환경에 다크모드를 적용해보자.

www.d5br5.dev