THE DEVLOG

scribbly.

Next JS 치트 시트

2025.05.16 04:41:19

Next.js 15 App Router (React Server Component 기반)에서는 CSS-in-JS 방식이 기존 CSR (클라이언트 사이드 렌더링)과 다르게 제한적으로 동작하거나 안정성이 떨어진다.

따라서 일반적인 CSS-in-JS보다는 CSS-in-JS대체인 vanilla-extractTailwindCSS를 사용하게 된다. 이 글에서는 TailwindCSS에 대해 설명한다.

App Router에서 CSS-in-JS 방식이 불안정한 이유

핵심 원인: React Server Components (RSC)의 동작 방식

  • Next.js 15의 App Router는 RSC를 사용.
  • RSC는 서버에서 React 트리 렌더 → RSC Payload → 클라이언트 Hydration.
  • 서버에서 실행되는 코드에는 브라우저 API(document, window, DOM 접근 등)가 없음.
  • **CSS-in-JS (예: styled-components, emotion)**는 일반적으로 런타임에 브라우저 환경에서 동적으로 CSS 생성 및 주입.

문제 발생

방식문제 원인
styled-components서버에서 스타일 생성 불가능 (스타일 태그 주입할 DOM 없음)
emotion동일. RSC 환경에서 작동 불안정 (CSS-in-JS 라이브러리 대부분이 클라이언트 기반으로 만들어짐)
vanilla-extract서버 컴파일 시 별도 CSS 파일을 만들어 빌드 시점에 생성 가능 → 상대적으로 안정적 (Runtime X)

요약:

App Router는 서버 전용 코드에서 CSS 동적 생성 자체가 무의미하거나 Hydration 중 충돌 가능.
특히 RSC는 클라이언트와 서버가 동일한 실행 컨텍스트를 공유하지 않으므로 CSS-in-JS 런타임 접근 불가.

Tailwind CSS가 App Router에서 거의 표준처럼 쓰이는 이유

Atomic CSS → Build-time 생성 → Pure HTML처럼 처리 가능

  • Tailwind는 미리 정의된 클래스 → HTML에 클래스 문자열만 붙임 → 서버에서도 안전하게 렌더 가능.
  • 브라우저 동작 필요 X → 서버에서도 바로 HTML과 동일하게 처리.
  • 스타일 충돌 없음 → 스타일 시트가 빌드 타임에 미리 완성 → 서버가 별도 관리 X.

App Router 친화성

Tailwind 특징App Router 최적화 이유
클래스 기반 Static CSSRSC에서 문제 없음 (CSS는 HTML에 포함되므로 서버/클라이언트 모두 안정적)
미리 빌드된 글로벌 CSS서버에서 즉시 사용 가능, 별도 런타임 필요 없음
Dynamic class name 지원Next.js 15에서는 서버와 클라이언트 모두에서 유연하게 사용 가능

요약:

Tailwind는 브라우저 DOM 접근 없이 서버에서 HTML과 CSS를 즉시 렌더링 가능.
RSC 환경에서도 충돌 없이 SSR + CSR 양쪽 모두에서 호환.

 

Tailwind 기초 문법

Atomic CSS 방식

  • Utility-First 지향
  • CSS 속성이 아닌 클래스 이름 자체가 스타일 속성
  • 예:
<div class="text-lg font-bold text-red-500 bg-gray-100 p-4 rounded"></div>

Tailwind 클래스의미
text-lg폰트 크기 Large
font-bold폰트 두껍게
text-red-500텍스트 색상 빨간색 (500 단계)
bg-gray-100배경색 회색 (100 단계)
p-4패딩 1rem
rounded모서리 둥글게

2. Theme (custom theme)

📍 tailwind.config.js 확장

/** @type {import('tailwindcss').Config} */
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: '#1e40af',
        secondary: '#64748b',
      },
      spacing: {
        '128': '32rem',
      },
    },
  },
};

  • extend 사용 → 기본 테마 유지 + 추가 가능
  • colors.primary, spacing.128 식으로 사용 가능
<div class="bg-primary p-128 text-white"></div>

3. 다크모드 설정 방법

Tailwind의 2가지 다크모드 지원

방식설명장점/단점
class<html class="dark"> 존재 여부로 다크/라이트사용자가 토글 가능, JS로 상태 관리 쉬움
media(prefers-color-scheme: dark) 사용자동 감지 가능, JS 필요 없음, 제어 어려움

tailwind.config.js

module.exports = {
  darkMode: 'class', // 또는 'media'
};

사용 예시

<!-- class 방식 -->
<html class="dark">
  <div class="bg-white dark:bg-black text-black dark:text-white">Hello</div>
</html>

<!-- media 방식 (자동) -->
<div class="bg-white dark:bg-black text-black dark:text-white">Hello</div>

4. 기타 심화 기능

4.1. 상태 기반 클래스

<button class="hover:bg-blue-500 focus:ring-2 active:scale-95">Click me</button>

4.2. Group hover

<div class="group">
  <p class="group-hover:text-red-500">Hover parent changes me</p>
</div>

4.3. Responsive

<div class="text-base md:text-lg lg:text-xl">Responsive Text</div>

4.4. Theme-aware (with dark)

<div class="bg-white text-black dark:bg-black dark:text-white">Theme-aware</div>

4.5. Arbitrary value (임의 값)

<div class="bg-[#123456] p-[10px]">Arbitrary</div>

4.6. CSS 변수와 함께 사용

:root {
  --custom-color: #123456;
}

<div class="text-[var(--custom-color)]">With CSS Variable</div>