0263

FE

[Next.js] Next.js 15 + TailwindCSS 적용 시 마주한 문제와 새로운 설정 방식 (2025 최신 정리)

시작하며

Next.js 15에서는 TailwindCSS를 도입하는 방식이 예전과 다르게 바뀌었다.

특히, 프로젝트 초기화 시 tailwind.config.js 파일이 생성되지 않거나, globals.css 파일이 예전처럼 구성되지 않는 점에서 많은 혼란이 있었다.

이번 글에서는 Next.js 15 + TailwindCSS 프로젝트 초기화 시 마주했던 문제와 해결 방법, 그리고 Inline Theme 방식 등 새롭게 도입된 개념들을 정리해보려고 한다.

1. Next.js 15에서 TailwindCSS 설치 시 마주한 문제

1) 문제 상황

code
✔ Would you like to use Tailwind CSS? … Yes

Next.js 15에서는 create-next-app 명령어로 프로젝트를 생성할 때, 위의 내용 같이 옵션을 Yes로 선택하면 TailwindCSS가 자동으로 설치되지만, tailwind.config.js 파일이 기본적으로 생성되지 않는다.

CSS
@tailwind base;
@tailwind components;
@tailwind utilities;

또한, /src/app/globals.css 파일을 열어보면, 우리가 기존에 익숙했던 이런 선언도 보이지 않고, 대신 아래와 같은 구조로 되어 있다.

CSS
@import "tailwindcss";

:root {
  --background: #ffffff;
  --foreground: #171717;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}

2) 왜 이렇게 바뀌었을까?

이는 Next.js 15에서 TailwindCSS를 더욱 최적화된 형태로 불러오기 위해 도입된 새로운 방식(Inline Theme 방식) 때문이다.

2. Inline Theme (@theme inline) 방식이란?

기존 TailwindCSS는 tailwind.config.js 파일에서 theme를 확장하고, 이를 기반으로 CSS 유틸리티 클래스를 만들어내는 방식이었다.

하지만 Next.js 15 Starter에서는 CSS 파일 내에서 직접 테마 변수를 정의하고, 이를 사용하는 Inline Theme 방식을 채택했다.

CSS
:root {
  --background: #ffffff;
  --foreground: #171717;
}

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
}

이렇게 하면 config 파일 없이도 CSS 변수 기반으로 유연한 스타일링이 가능해진다.

(Next.js 팀이 속도 최적화와 간결한 초기 세팅을 위해 도입한 방식이다.)

1) 하지만, 이 방식의 한계점

Tailwind 유틸리티 클래스를 자유롭게 확장하려면 결국 tailwind.config.js 또는 tailwind.config.ts를 쓰는 게 편하다.

기존 방식에 익숙한 사용자들은 오히려 불편하게 느껴질 수 있다.

3. 기존의 module.exports 방식이 아닌 Config 방식으로 변경된 이유

Tailwind 3.3 이후부터는 ESM(ES Modules)을 기본으로 지원한다.

Next.js 15는 이 흐름에 맞춰 tailwind.config.js 대신 tailwind.config.ts 또는 .mjs 포맷을 권장한다.

YAML
module.exports = {
  content: [...],
  theme: { extend: {} },
}

기존에는 위와 같이 썼던 설정이 이제는 TypeScript 기반에서는 아래와 작성하는 걸 권장한다.

code
import type { Config } from 'tailwindcss';

const config: Config = {
  content: [...],
  theme: { extend: {} },
  plugins: [],
};

export default config;

1) 왜 이렇게 바뀌었는가?

  • Next.js가 ESM(ES Module)을 기본으로 채택하면서 CommonJS(module.exports) 방식에서 벗어나기 시작했기 때문이다.

  • Tailwind 팀도 이에 맞춰 export default 방식과 Config 타입을 제공하는 패턴으로 정리한 것이다.

4. globals.css에서 @tailwind base/components/utilities를 사용하지 않는 이유

Next.js 15 Starter에서는 PostCSS 플러그인 체인 안에서 TailwindCSS를 먼저 import 해주는 방식을 사용한다.

CSS
@import "tailwindcss";

이렇게만 해도 TailwindCSS의 base, components, utilities가 모두 불러와진다.

CSS
@tailwind base;
@tailwind components;
@tailwind utilities;

하지만 우리가 위처럼 Tailwind에서 흔히 쓰던 방식은 사실 내부적으로 @import "tailwindcss";와 동일한 처리를 하게 된다.

Next.js 15 Starter에서는 PostCSS 설정을 더 간결하게 유지하기 위해 이 구조로 설계된 것이다.

5. 기존처럼 Tailwind 유틸리티를 자유롭게 쓰고 싶다면?

기본적으로는 @import “tailwindcss”; 만으로도 유틸리티 클래스를 사용할 수 있다.

하지만 유틸리티 확장이나 플러그인 사용을 위해서는 다음과 같이 진행하는 것이 좋다.

1) tailwind.config.ts 파일 직접 생성

code
import type { Config } from 'tailwindcss'

const config: Config = {
  content: [
    './src/app/**/*.{js,ts,jsx,tsx}',
    './src/components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

export default config;

2) globals.css는 그대로 두어도 됨

CSS
@import "tailwindcss";

:root {
  --background: #ffffff;
  --foreground: #171717;
}

/* 기존 @tailwind base; components; utilities; 는 @import "tailwindcss";로 통합 */

정리 — 핵심 포인트

바뀐 점

이해 포인트

tailwind.config.js 대신 tailwind.config.ts를 수동으로 생성

Next.js 15는 config 파일 없이도 기본 작동하지만, 확장을 원하면 만들어야 함

Inline Theme 방식 도입 (@theme inline)

CSS 변수 기반으로 더 간결한 테마 설정 (config 없이도 스타일링 가능)

globals.css에서 @tailwind base/components/utilities가 없음

@import “tailwindcss”; 한 줄로 대체됨 (내부적으로 동일하게 처리됨)

config 파일 작성 시 CommonJS가 아닌 ESM 기반

module.exports 대신 export default로 작성, Config 타입 적용

마치며

Next.js 15에서는 TailwindCSS를 더 간결하고 빠르게 적용할 수 있도록 구조를 변경했지만, 기존 방식에 익숙한 사람들에게는 오히려 혼란을 줄 수 있다.

중요한 건 Tailwind 설정을 자유롭게 확장하려면 tailwind.config.ts를 수동으로 추가하는 게 여전히 필요하다는 점이다.

Inline Theme 방식은 간단한 테마 커스터마이징에는 유용하지만, 클래스 기반의 Tailwind 확장성을 원한다면 기존 config 기반 접근법과 혼합하는 것이 가장 실용적인 방법이다.