NextJS 13.4 App Router + TailwindCss - ganOverflow 회고

hongregii·2023년 8월 3일
1

NextJS 13.4 App Router 회고를 간단히 tailwindcss 사용기부터 시작하려고 한다.

tailwindCss 왜씀

많은 장점이 있지만, 우리가 이번에 tailwind를 사용하기로 결정한 가장 큰 이유는 Next팀이 장려하고 있기 때문.

npx create-next-app@latest

를 CLI로 입력하면,

What is your project named?  my-app
Would you like to use TypeScript?  No / Yes
Would you like to use ESLint?  No / Yes
Would you like to use Tailwind CSS?  No / Yes
Would you like to use `src/` directory?  No / Yes
Would you like to use App Router? (recommended)  No / Yes
Would you like to customize the default import alias?  No / Yes

이 메세지가 뿅 나타난다. App Router를 사용할 것을 권고하는 것과 TypeScript, TailwindCss를 권고하는 것이 인상적이다.

다른 css 툴과 비교하면...

  • styled-components 와 비교하면, Boiler plate 코드가 적다. 컴포넌트를 따로 만들어서 사용할 필요가 없고 className 만 추가하면 되니까 개발 속도가 몇배 빠른 느낌. 특히 VSCode의 tailwind extension을 잘 활용하기를 강력히 추천한다. 사용할 수 있는 클래스명이 너무 많아서 문서로 찾기에는 비효율적이다. VSCode에서 사용할 수 있는 클래스명을 미리미리 확인해볼 수 있는게 매우 유익했다. (특히 색깔!)

  • Emotion 과 같은 css-in-js툴과 비교하면, 컴포넌트 내에서 스타일을 지정하는 아이디어는 공유하면서, 정해진 클래스네임을 사용한다는 점에서 개발 속도가 더 빠르다. tailwind는 이 툴과 단점도 공유하는데, 코드 읽기가 불편해질 수도 있다는 점일것 같다. 하지만 가독성이 그렇게까지 떨어지지는 않았다. 오히려 어차피 빠른 스타일 수정이 가능하기 때문에 생기는 장점이 더 컸음.

  • Bootstrap / Material UI와 비교하면, tailwind와 이 툴들은 다루는 영역과 접근 방식이 꽤 다르다. BS/MUI는 다 만들어진 컴포넌트를 제공해서 커스터마이징이 불편하고, tailwind는 사실상 css를 더 빠르게 작성하게 해주는 접근.

  • sass와 비교하면, css를 완전히 jsx/tsx 코드와 분리하는 sass는 개발자만 있는 프로젝트에서는 그렇게 썩 마음에 안들었다. 아마 sass를 잘 사용하는 퍼블리싱 인력이 팀에 있을 때 더 효율적인 방식이 아닐까 싶다. 개발자는 기능 구현에만 집중, 스타일링은 퍼블리셔가 담당하는 식. 사실 react/next를 사용하면 이러한 접근의 장점이 죽는 것 같다. 지역 스타일링, 코로케이션 같은 철학이 전체 페이지보다는 컴포넌트 단위의 렌더링이 많은 react/next에 더 어울리지 않나 싶다. 이게 next팀이 tailwindcss를 권장하는 이유라고 생각되기도.

다크모드

tailwindcss를 NextJS App Router에서 사용하며 특이했던 기능을 회고하자면 단연 다크모드 구현이었다.

tailwind는 default로 다크모드 구현을 지원하는데, 브라우저 세팅을 보고 활성화된다. tailwind className 중 "dark:<클래스명>"을 사용하면, 브라우저 세팅 (보통 OS 세팅을 따라감) 에 따라 다크모드가 활성화돼있을 때 해당 style이 발동된다.

그러나 script로 브라우저 세팅을 바꿀 수는 없다고 한다. 그래서 tailwind는 상위 컴포넌트의 class 기반으로도 다크모드를 켤 수 있게 지원한다.

// tailwind.config.js 에서
module.exports = {
  darkMode: 'class',
  // ...
}

를 추가하면,

<!-- Dark mode enabled -->
<html class="dark"> // ← 이부분 주목!
<body>
  <!-- Will be black -->
  <div class="bg-white dark:bg-black">
    <!-- ... -->
  </div>
</body>
</html>

아래와 같은 컴포넌트에서 (SSR, CSR 관계없이)
부모 컴포넌트에 "dark"라는 클래스명이 있을 때, 자식 컴포넌트의 "dark:<스타일명>"의 스타일이 발동된다.

이 프로젝트는 최상단(부모) 컴포넌트인 RootLayout이 CSR이었기 때문에...
그냥 최상단 컴포넌트에서 isDarkMode State를 boolean 값으로 선언했다. 바로 아래 자식인 Header 컴포넌트에 isDarkMode를 prop으로 내려줬고, isDarkMode가 true일때 RootLayout의 html 태그 className에 "dark"를 추가했다.

// layout.tsx --> function RootLayout() 중
 const [isDarkMode, setIsDarkMode] = useState(true);
  const toggleDarkMode = () => {
    setIsDarkMode((prev) => !prev);
  };
  return (
    <html
      lang="en"
      className={`${inter.className} h-full scroll-smooth antialiased`}
      className={`${inter.className} ${
        isDarkMode ? "dark" : ""
      } h-full scroll-smooth antialiased`}
    >
      <CapsulizedHead />
      <RecoilRoot>
        <body className="flex min-h-full flex-col">
          <Header toggleDarkMode={toggleDarkMode} isDarkMode={isDarkMode} />
          <main className="grow pt-[44px] md:pt-[68px] bg-slate-300 dark:bg-slate-800 dark:text-slate-100">
            {children}
          </main>
... (생략) ...

영향을 받는 자식 컴포넌트는 RootLayout의 <main> 컴포넌트다. 부모 요소인 <html>의 className에 "dark"가 있으면, <main>의 dark:bg-slate-800, dark:text-slate-100 클래스가 발동된다.

마치며

전반적으로 tailwind css와 nextJS의 궁합은 참 찰떡같았다. CSR/SSR 컴포넌트 단위 개발에 익숙해져가며, 요소에 스타일이 착 붙어있으면서도, styled-components보다 더 빠르게 스타일링을 하는 게 매우 편하고 무엇보다 빨랐다.

profile
잡식성 누렁이 개발자

0개의 댓글