Post

[Trouble Shooting] Tailwind CSS v4 마이그레이션: @apply 제거와 PostCSS 설정 변경

Tailwind CSS v4 업그레이드 시 발생한 PostCSS, @apply, CSS 변수 문제 해결

문제 상황

Tailwind CSS를 v3에서 v4로 업그레이드했더니 다음과 같은 오류들이 발생함:

  1. PostCSS 플러그인 오류: It looks like you're trying to use 'tailwindcss' directly as a PostCSS plugin
  2. Unknown utility class 오류: Cannot apply unknown utility class 'border-border'
  3. 최대 재귀 깊이 초과: Exceeded maximum recursion depth
  4. CSS 변수 문법 오류: w-[--sidebar-width]가 작동하지 않음
  5. 사이드바 레이아웃 깨짐: 메인 콘텐츠 위에 사이드바가 겹쳐짐

문제 1: PostCSS 플러그인 오류

오류 메시지

1
2
[plugin:vite:css] [postcss] It looks like you're trying to use 'tailwindcss' directly as a PostCSS plugin.
The PostCSS plugin has moved to a separate package.

원인

Tailwind CSS v4부터 PostCSS 플러그인이 별도 패키지(@tailwindcss/postcss)로 분리됨.

해결 방법

1. 패키지 설치

1
pnpm add -D @tailwindcss/postcss

2. PostCSS 설정 변경

Before (v3):

1
2
3
4
5
6
7
// postcss.config.js
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
};

After (v4):

1
2
3
4
5
6
// postcss.config.js
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};

autoprefixer는 v4에 내장되어 있으므로 제거해도 됨.


문제 2: Unknown Utility Class 오류

오류 메시지

1
[postcss] tailwindcss: Cannot apply unknown utility class 'border-border'

원인

Tailwind v4에서 @tailwind 지시어 대신 @import "tailwindcss"를 사용해야 함.

해결 방법

Before (v3):

1
2
3
4
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

After (v4):

1
2
/* globals.css */
@import "tailwindcss";

주의: @import "tailwindcss"는 반드시 파일 최상단에 위치해야 함.


문제 3: 최대 재귀 깊이 초과

오류 메시지

1
[plugin:@tailwindcss/vite:generate:serve] Exceeded maximum recursion depth while resolving 'tailwindcss/utilities'

원인

  1. node_modules 손상
  2. @theme 블록과 tailwind.config.ts 충돌
  3. @layer 내부의 순환 참조

해결 방법

1. node_modules 완전 재설치

1
2
rm -rf node_modules pnpm-lock.yaml
pnpm install

2. 빌드 캐시 삭제

1
rm -rf .vite dist

대부분의 경우 깨끗한 재설치로 해결됨.


문제 4: @layer와 @apply 호환성 문제

원인

Tailwind v4는 @layer@apply 지시어를 레거시로 간주하며, CSS-first 접근 방식을 권장함.

해결 방법

모든 @layer@apply를 명시적 CSS로 변환해야 함.

Before (v3 - @apply 사용)

1
2
3
4
5
6
7
8
9
10
11
12
13
@layer base {
  * {
    @apply border-border;
  }

  body {
    @apply bg-background text-foreground antialiased;
  }

  h1 {
    @apply text-4xl font-bold;
  }
}

After (v4 - 명시적 CSS)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
* {
  border-color: hsl(var(--border));
}

body {
  background-color: hsl(var(--background));
  color: hsl(var(--foreground));
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

h1 {
  font-size: 2.25rem;
  line-height: 2.5rem;
  font-weight: 700;
}

변환 가이드

v3 (@apply)v4 (명시적 CSS)
@apply text-primarycolor: hsl(var(--primary));
@apply bg-backgroundbackground-color: hsl(var(--background));
@apply border-borderborder-color: hsl(var(--border));
@apply text-smfont-size: 0.875rem; line-height: 1.25rem;
@apply font-boldfont-weight: 700;

문제 5: CSS 변수 문법 변경

오류

Arbitrary value에서 CSS 변수를 사용할 때 스타일이 적용되지 않음.

1
2
// ❌ v4에서 작동 안 함
<div className="w-[--sidebar-width]">

원인

Tailwind v4에서 CSS 변수를 arbitrary value로 사용할 때 var() 함수가 필수가 됨.

해결 방법

Before (v3)

1
2
<div className="w-[--sidebar-width]">
<div className="h-[--header-height]">

After (v4)

1
2
<div className="w-[var(--sidebar-width)]">
<div className="h-[var(--header-height)]">

사이드바 레이아웃 수정 예시

1
2
3
4
5
6
7
// Sidebar.tsx
<div className="relative w-[var(--sidebar-width)] bg-transparent">
  {/* Spacer div - 공간 확보 */}
</div>
<div className="fixed w-[var(--sidebar-width)]">
  {/* 실제 사이드바 컨텐츠 */}
</div>

주의: style 속성에서는 var() 없이 사용 가능:

1
<div style={{ "--sidebar-width": "16rem" } as React.CSSProperties} />

문제 6: 커스텀 유틸리티 클래스 미생성

문제

프로젝트에서 사용하는 text-muted-foreground, bg-accent 등의 클래스가 생성되지 않음.

원인

v4에서 @import "tailwindcss" 사용 시 tailwind.config.tstheme.extend.colors가 자동으로 유틸리티 클래스를 생성하지 않음.

해결 방법

필요한 클래스를 globals.css에 직접 정의:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* globals.css */

/* Text Color Utilities */
.text-foreground {
  color: hsl(var(--foreground));
}

.text-muted-foreground {
  color: hsl(var(--muted-foreground));
}

.text-primary {
  color: hsl(var(--primary));
}

/* Background Utilities */
.bg-background {
  background-color: hsl(var(--background));
}

.bg-muted {
  background-color: hsl(var(--muted));
}

.bg-accent {
  background-color: hsl(var(--accent));
}

/* Border Utilities */
.border {
  border-width: 1px;
}

.border-border {
  border-color: hsl(var(--border));
}

결과

Before

  • PostCSS 플러그인 오류로 빌드 실패
  • @apply 사용으로 인한 레거시 경고
  • CSS 변수 문법 오류로 사이드바 레이아웃 깨짐
  • 커스텀 유틸리티 클래스 미생성

After

  • 빌드 성공 및 모든 오류 제거
  • 명시적 CSS로 변환하여 레거시 제거
  • CSS 변수 문법 수정으로 레이아웃 정상화
  • 필요한 유틸리티 클래스 직접 정의

마이그레이션 체크리스트

1. 패키지 설치

1
pnpm add -D @tailwindcss/postcss

2. PostCSS 설정 변경

1
2
3
4
5
6
// postcss.config.js
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};

3. CSS Import 문법 변경

1
2
/* globals.css */
@import "tailwindcss";

4. @layer와 @apply 제거

  • 모든 @layer 블록을 제거
  • 모든 @apply 지시어를 명시적 CSS로 변환

5. CSS 변수 문법 수정

  • \[--var\][var(--var)] 형식으로 변경
  • 프로젝트 전체 검색: \[--[var(--

6. 커스텀 유틸리티 클래스 정의

  • 자주 사용하는 클래스를 globals.css에 직접 정의

7. 의존성 재설치

1
2
rm -rf node_modules pnpm-lock.yaml .vite
pnpm install

8. 빌드 테스트

1
2
pnpm dev
pnpm build

주의할 점

1. @layer와 @apply는 완전히 제거해야 함

Tailwind v4는 CSS-first 접근을 강제하므로, 기존 @apply 방식을 계속 사용하면 경고가 발생함.

2. CSS 변수는 클래스에서만 var() 필수

1
2
3
4
5
// ✅ 클래스에서는 var() 사용
<div className="w-[var(--sidebar-width)]">

// ✅ style 속성에서는 var() 없이 사용
<div style={{ width: 'var(--sidebar-width)' }}>

3. 재귀 오류는 node_modules 재설치로 해결

빌드 중 재귀 오류가 발생하면 node_modules를 삭제하고 재설치하는 것이 가장 확실한 해결책임.

4. 브라우저 캐시 확인

스타일 변경이 반영되지 않으면 브라우저 하드 리프레시(Ctrl + Shift + R)를 시도.


Tailwind CSS v4 마이그레이션은 PostCSS 설정 변경, @apply 제거, CSS 변수 문법 수정이 핵심이었음. 레거시 방식을 완전히 제거하고 CSS-first 접근으로 전환하여 더 명확한 스타일 관리가 가능해짐.

도움이 되셨길 바랍니다! 😀

This post is licensed under CC BY 4.0 by the author.