CSS
Next.js는 CSS를 처리하는 여러 가지 방법을 지원합니다:
CSS 모듈
Next.js는 .module.css
확장자를 사용하여 CSS 모듈을 기본적으로 지원합니다.
CSS 모듈은 자동으로 고유한 클래스 이름을 생성하여 CSS의 범위를 한정합니다. 이를 통해 다른 파일에서 동일한 클래스 이름을 사용해도 충돌을 걱정할 필요가 없습니다. 이러한 특성으로 인해 CSS 모듈은 컴포넌트 수준의 CSS를 포함하는 이상적인 방법입니다.
예시
CSS 모듈은 app
디렉토리 내의 모든 파일에서 가져올 수 있습니다:
import styles from "./styles.module.css";
export default function DashboardLayout({
children,
}: {
children: React.ReactNode;
}) {
return <section className={styles.dashboard}>{children}</section>;
}
import styles from "./styles.module.css";
export default function DashboardLayout({ children }) {
return <section className={styles.dashboard}>{children}</section>;
}
.dashboard {
padding: 24px;
}
CSS 모듈은 .module.css
및 .module.sass
확장자를 가진 파일에서만 활성화됩니다.
프로덕션 환경에서는 모든 CSS 모듈 파일이 자동으로 여러 개의 축소되고 코드 분할된 .css
파일로 연결됩니다.
이러한 .css
파일은 애플리케이션의 주요 실행 경로를 나타내어 애플리케이션 렌더링에 필요한 최소한의 CSS만 로드되도록 합니다.
전역 스타일
전역 스타일은 app
디렉토리 내의 모든 레이아웃, 페이지 또는 컴포넌트로 가져올 수 있습니다.
알아두면 좋은 점:
- 이는
pages
디렉토리와 다릅니다.pages
디렉토리에서는_app.js
파일 내에서만 전역 스타일을 가져올 수 있습니다.- Next.js는 실제로 전역적이지 않은 전역 스타일의 사용을 지원하지 않습니다. 즉, 모든 페이지에 적용될 수 있고 애플리케이션의 수명 동안 유지될 수 있는 스타일만 사용해야 합니다. 이는 Next.js가 서스펜스와 통합하기 위해 React의 내장 스타일시트 지원을 사용하기 때문입니다. 이 내장 지원은 현재 경로 간 이동 시 스타일시트를 제거하지 않습니다. 이러한 이유로, 전역 스타일보다는 CSS 모듈 사용을 권장합니다.
예를 들어, app/global.css
라는 스타일시트를 고려해 봅시다:
body {
padding: 20px 20px 60px;
max-width: 680px;
margin: 0 auto;
}
루트 레이아웃(app/layout.js
) 내에서 global.css
스타일시트를 가져와 애플리케이션의 모든 경로에 스타일을 적용합니다:
// 이 스타일은 애플리케이션의 모든 경로에 적용됩니다
import "./global.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
// 이 스타일은 애플리케이션의 모든 경로에 적용됩니다
import "./global.css";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
외부 스타일시트
외부 패키지에서 게시된 스타일시트는 app
디렉토리 어디에서나 가져올 수 있으며, 여기에는 동일한 위치에 있는 컴포넌트도 포함됩니다:
import "bootstrap/dist/css/bootstrap.css";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body className="container">{children}</body>
</html>
);
}
import "bootstrap/dist/css/bootstrap.css";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className="container">{children}</body>
</html>
);
}
알아두면 좋은 점: 외부 스타일시트는 npm 패키지에서 직접 가져오거나 코드베이스와 동일한 위치에 다운로드하여 사용해야 합니다.
<link rel="stylesheet" />
를 사용할 수 없습니다.
순서 및 병합
Next.js는 프로덕션 빌드 중에 자동으로 스타일시트를 분할(병합)하여 CSS를 최적화합니다. CSS 순서는 애플리케이션 코드에서 스타일시트를 가져오는 순서에 의해 결정됩니다.
예를 들어, <Page>
에서 <BaseButton>
을 먼저 가져오기 때문에 base-button.module.css
가 page.module.css
보다 먼저 정렬됩니다:
import styles from "./base-button.module.css";
export function BaseButton() {
return <button className={styles.primary} />;
}
import styles from "./base-button.module.css";
export function BaseButton() {
return <button className={styles.primary} />;
}
import { BaseButton } from "./base-button";
import styles from "./page.module.css";
export function Page() {
return <BaseButton className={styles.primary} />;
}
import { BaseButton } from "./base-button";
import styles from "./page.module.css";
export function Page() {
return <BaseButton className={styles.primary} />;
}
예측 가능한 순서를 유지하기 위해 다음을 권장합니다:
- CSS 파일은 하나의 JS/TS 파일에서만 가져옵니다.
- 전역 클래스 이름을 사용하는 경우, 적용하고자 하는 순서대로 동일한 파일에서 전역 스타일을 가져옵니다.
- 전역 스타일보다는 CSS 모듈을 선호합니다.
- CSS 모듈에 일관된 명명 규칙을 사용합니다. 예를 들어,
<name>.tsx
대신<name>.module.css
를 사용합니다.
- CSS 모듈에 일관된 명명 규칙을 사용합니다. 예를 들어,
- 공유 스타일을 별도의 공유 컴포넌트로 추출합니다.
- Tailwind를 사용하는 경우, 파일 상단에서 스타일시트를 가져옵니다. 가급적 루트 레이아웃에서 가져오는 것이 좋습니다.
- 가져오기를 자동으로 정렬하는 린터/포맷터(예: ESLint의
sort-import
)를 끕니다. 이는 CSS 가져오기 순서에 영향을 줄 수 있으며, CSS 순서는 중요하기 때문입니다.
알아두면 좋은 점:
- 개발 모드에서는 CSS 순서가 다르게 동작할 수 있으므로, 항상 빌드(
next build
)를 확인하여 최종 CSS 순서를 검증하세요.next.config.js
의cssChunking
옵션을 사용하여 CSS가 분할되는 방식을 제어할 수 있습니다.
추가 기능
Next.js는 스타일 추가 경험을 개선하기 위한 추가 기능을 포함하고 있습니다:
next dev
로 로컬에서 실행할 때, 로컬 스타일시트(전역 또는 CSS 모듈)는 Fast Refresh를 활용하여 편집 내용이 저장되는 즉시 반영됩니다.next build
로 프로덕션 빌드 시, CSS 파일은 더 적은 수의 축소된.css
파일로 번들링되어 스타일을 검색하는 데 필요한 네트워크 요청 수를 줄입니다.- JavaScript를 비활성화해도 프로덕션 빌드(
next start
)에서 스타일은 계속 로드됩니다. 그러나 Fast Refresh를 활성화하기 위해next dev
에서는 여전히 JavaScript가 필요합니다.