Next.js CSS 정리

Next.js Docs – Getting Started: CSS 페이지를 기반으로, App Router 환경에서 스타일을 적용하는 방법을 정리한 문서입니다.


1. 개요

Next.js는 애플리케이션에 CSS를 적용하기 위해 여러 가지 방식을 제공합니다.

  • Tailwind CSS
  • CSS Modules
  • Global CSS
  • External Stylesheets (외부 스타일시트)
  • 그 밖에 별도 문서로 다루는 Sass, CSS-in-JS

App Router에서는 이 스타일링 방식을 레이아웃(app/layout.tsx)과 각 페이지/컴포넌트 수준에서 조합해 사용할 수 있습니다.


2. Tailwind CSS

2.1 Tailwind CSS란?

  • Tailwind CSS는 유틸리티 클래스 기반(utility-first)의 CSS 프레임워크입니다.
  • 미리 만들어진 유틸리티 클래스를 조합하여, 빠르게 커스텀 디자인을 만들 수 있습니다.
  • 예: flex, min-h-screen, items-center, text-4xl, font-bold 등.

2.2 설치

Tailwind CSS와 관련 PostCSS 플러그인을 개발 의존성으로 설치합니다.

pnpm add -D tailwindcss @tailwindcss/postcss

2.3 PostCSS 설정

postcss.config.mjs 파일에서 Tailwind PostCSS 플러그인을 등록합니다.

// postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
}

2.4 글로벌 CSS에서 Tailwind 불러오기

글로벌 스타일 파일에서 Tailwind를 import 합니다.

/* app/globals.css */
@import 'tailwindcss';

2.5 루트 레이아웃에서 CSS import

app/layout.tsx에서 글로벌 CSS를 한 번만 import 합니다.

// app/layout.tsx
import './globals.css'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

2.6 Tailwind 유틸리티 클래스 사용 예시

// app/page.tsx
export default function Page() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-between p-24">
      <h1 className="text-4xl font-bold">Welcome to Next.js!</h1>
    </main>
  )
}

2.7 구형 브라우저 지원

  • 매우 구형 브라우저까지 지원해야 할 경우, Tailwind CSS v3 설정 가이드를 참고하는 것이 권장됩니다.
  • 기본적으로 최신 브라우저 환경을 주 대상으로 합니다.

3. CSS Modules

3.1 개념

  • CSS Modules는 CSS를 컴포넌트 단위로 로컬 스코프(local scope) 처리합니다.
  • 각 클래스 이름에 대해 빌드 시 고유한 해시 기반 이름을 생성하여, 네이밍 충돌을 방지합니다.
  • 동일한 클래스 이름을 여러 파일에서 사용해도 서로 영향을 주지 않습니다.

3.2 사용법

  1. 파일 이름을 *.module.css 형식으로 작성합니다.
  2. 컴포넌트에서 import styles from './파일명.module.css' 형태로 불러와 사용합니다.
/* app/blog/blog.module.css */
.blog {
  padding: 24px;
}
// app/blog/page.tsx
import styles from './blog.module.css'

export default function Page() {
  return <main className={styles.blog}></main>
}
  • styles.blog처럼 객체 프로퍼티 형태로 클래스 이름을 참조합니다.
  • 빌드 결과물에서는 실제로는 난수/해시가 섞인 클래스명이 되지만, 컴포넌트에서는 타입 안전하게 사용할 수 있습니다.

4. Global CSS

4.1 개념

  • Global CSS는 애플리케이션 전체에 공통으로 적용되는 스타일입니다.
  • body, html, a, button 등에 대한 사이트 전역 스타일을 정의할 때 사용합니다.

4.2 설정 방법

  1. app/global.css (또는 globals.css) 파일을 생성합니다.
  2. 루트 레이아웃(app/layout.tsx)에서 한 번만 import 합니다.
/* app/global.css */
body {
  padding: 20px 20px 60px;
  max-width: 680px;
  margin: 0 auto;
}
// app/layout.tsx
// These styles apply to every route in the application
import './global.css'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

4.3 주의할 점 (Good to know)

  • Global CSS는 app 디렉토리 안의 어떤 layout, page, component에서도 import 할 수는 있지만,
    Next.js는 React의 스타일시트 지원 + Suspense 통합 구조 때문에 라우트 이동 시 스타일시트를 제거하지 않습니다.
  • 이로 인해 여러 경로에 걸쳐 글로벌 스타일이 겹치면서 충돌이 발생할 수 있습니다.
  • 따라서 권장 패턴은 다음과 같습니다.
    • 정말 전역이어야 하는 스타일(Reset, 기본 타이포그래피 등)에만 Global CSS 사용
    • 대부분의 컴포넌트 스타일은 Tailwind 유틸리티 클래스 사용
    • Tailwind로 커버하기 어려운 곳에만 CSS Modules로 개별 스타일 정의

5. External Stylesheets (외부 스타일시트)

5.1 개념

  • 외부 라이브러리(예: Bootstrap)에서 제공하는 CSS 파일을 곧바로 import 해서 사용할 수 있습니다.
  • app 디렉토리 어디에서든 import 가능하며, 루트 레이아웃에 두는 것이 일반적입니다.

5.2 예시 (Bootstrap 사용)

// app/layout.tsx
import 'bootstrap/dist/css/bootstrap.css'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className="container">{children}</body>
    </html>
  )
}
  • 위 예제에서는 Bootstrap 컨테이너 클래스를 body에 직접 적용했습니다.
  • React 19에서는 <link rel="stylesheet" href="..."> 방식도 지원합니다.
  • Next.js App Router에서는 CSS import 방식<link> 방식을 상황에 맞게 선택할 수 있습니다.

6. CSS Ordering and Merging (순서와 병합)

6.1 프로덕션 빌드에서의 최적화

  • 프로덕션 빌드(next build) 시, Next.js는 CSS를 자동으로 분할(chunking)하고 병합(merging) 합니다.
  • 각 라우트가 필요로 하는 최소한의 CSS만 로드되도록 코드 스플리팅을 수행합니다.

6.2 CSS 순서

  • 최종적인 CSS의 적용 순서는 코드에서 import 하는 순서에 영향을 받습니다.
  • 예를 들어, 아래 코드에서는 BaseButton에서 import 하는 CSS가 먼저, page.module.css가 나중에 로드됩니다.
// app/page.tsx
import { BaseButton } from './base-button'
import styles from './page.module.css'

export default function Page() {
  return <BaseButton className={styles.primary} />
}
// app/base-button.tsx
import styles from './base-button.module.css'

export function BaseButton({
  className,
}: {
  className?: string
}) {
  return <button className={`${styles.primary} ${className ?? ''}`} />
}
  • 이런 식으로 컴포넌트 import 순서CSS import 위치가 최종적인 스타일 우선순위에 영향을 줍니다.
  • 덮어써야 하는 스타일일수록 나중에 import 되는 CSS 파일에서 정의하는 것이 안전합니다.

7. Recommendations (권장 사항)

문서에서 제안하는 CSS 사용 권장 사항은 다음과 같습니다.

  1. CSS import 위치를 최대한 한 곳으로 모으기

    • 여러 파일에서 CSS를 중구난방으로 import 하기보다는,
    • 단일 엔트리 파일(예: 루트 레이아웃)에 정리하는 것이 예측 가능한 순서를 만듭니다.
  2. Global 스타일과 Tailwind 스타일은 앱 루트에서 import

    • app/layout.tsx와 같이 앱 루트에 가까운 위치에서
    • global.css, globals.css, Tailwind import를 처리합니다.
  3. 대부분의 스타일은 Tailwind CSS로 처리

    • 공통적인 레이아웃/타이포/색상 등은 Tailwind 유틸리티 클래스 조합으로 해결합니다.
  4. Tailwind로 표현하기 애매한 부분은 CSS Modules로 보완

    • 복잡한 애니메이션, 특정 DOM 구조에 딱 맞춘 스타일 등은 CSS Modules로 정의합니다.
  5. CSS Modules 이름 규칙 통일

    • <name>.module.css와 같은 형태로 일관되게 사용합니다.
    • 컴포넌트 파일명과 CSS 모듈 파일명을 맞춰 두면 관리가 편해집니다.
  6. 공통 스타일은 공통 컴포넌트로 추출

    • 여러 곳에서 같은 스타일이 필요하다면,
    • CSS만 복붙하지 말고 공통 컴포넌트로 추출하여 중복 import를 줄입니다.
  7. 자동 import 정렬 기능 주의

    • ESLint의 sort-imports와 같이 import를 자동 정렬하는 기능은 CSS 순서 예측을 어렵게 만들 수 있습니다.
    • CSS import 순서가 중요한 프로젝트에서는 이런 기능을 끄거나, CSS import에 대해서는 예외를 두는 것이 안전합니다.
  8. cssChunking 옵션 활용

    • next.config.jscssChunking 옵션을 사용하면, CSS가 어떻게 청크로 나뉘는지 제어할 수 있습니다.

8. Development vs Production

개발/프로덕션 환경에서의 CSS 동작 차이는 다음과 같습니다.

  • 개발(next dev)

    • CSS 수정 사항이 Fast Refresh를 통해 거의 실시간으로 반영됩니다.
    • JavaScript가 Fast Refresh에 사용되므로, 개발 중에는 브라우저에서 JS가 반드시 활성화되어 있어야 합니다.
  • 프로덕션(next build + next start)

    • 모든 CSS 파일이 여러 개의 최소화(minified)되고 코드 스플릿된 .css 파일로 병합됩니다.
    • 각 라우트는 필요한 CSS만 로드하여, 초기 로딩 성능을 최적화합니다.
    • JavaScript가 꺼져 있어도 CSS는 로드됩니다. (단, 개발 환경의 Fast Refresh는 JS 의존)
  • 주의

    • 개발과 프로덕션에서 최종 CSS 순서가 다르게 보일 수 있으므로,
      실제 배포 전에는 반드시 next build 결과를 확인하여 스타일 충돌 여부를 점검하는 것이 좋습니다.