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 사용법
- 파일 이름을
*.module.css형식으로 작성합니다. - 컴포넌트에서
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 설정 방법
app/global.css(또는globals.css) 파일을 생성합니다.- 루트 레이아웃(
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에 직접 적용했습니다.
5.3 React 19와 <link>
- 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 사용 권장 사항은 다음과 같습니다.
-
CSS import 위치를 최대한 한 곳으로 모으기
- 여러 파일에서 CSS를 중구난방으로 import 하기보다는,
- 단일 엔트리 파일(예: 루트 레이아웃)에 정리하는 것이 예측 가능한 순서를 만듭니다.
-
Global 스타일과 Tailwind 스타일은 앱 루트에서 import
app/layout.tsx와 같이 앱 루트에 가까운 위치에서global.css,globals.css, Tailwind import를 처리합니다.
-
대부분의 스타일은 Tailwind CSS로 처리
- 공통적인 레이아웃/타이포/색상 등은 Tailwind 유틸리티 클래스 조합으로 해결합니다.
-
Tailwind로 표현하기 애매한 부분은 CSS Modules로 보완
- 복잡한 애니메이션, 특정 DOM 구조에 딱 맞춘 스타일 등은 CSS Modules로 정의합니다.
-
CSS Modules 이름 규칙 통일
<name>.module.css와 같은 형태로 일관되게 사용합니다.- 컴포넌트 파일명과 CSS 모듈 파일명을 맞춰 두면 관리가 편해집니다.
-
공통 스타일은 공통 컴포넌트로 추출
- 여러 곳에서 같은 스타일이 필요하다면,
- CSS만 복붙하지 말고 공통 컴포넌트로 추출하여 중복 import를 줄입니다.
-
자동 import 정렬 기능 주의
- ESLint의
sort-imports와 같이 import를 자동 정렬하는 기능은 CSS 순서 예측을 어렵게 만들 수 있습니다. - CSS import 순서가 중요한 프로젝트에서는 이런 기능을 끄거나, CSS import에 대해서는 예외를 두는 것이 안전합니다.
- ESLint의
-
cssChunking옵션 활용next.config.js의cssChunking옵션을 사용하면, 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 파일이 여러 개의 최소화(minified)되고 코드 스플릿된
-
주의
- 개발과 프로덕션에서 최종 CSS 순서가 다르게 보일 수 있으므로,
실제 배포 전에는 반드시next build결과를 확인하여 스타일 충돌 여부를 점검하는 것이 좋습니다.
- 개발과 프로덕션에서 최종 CSS 순서가 다르게 보일 수 있으므로,