Tailwind CSS v4 마이그레이션 가이드: 바뀐 것들과 업그레이드 방법 (2026)
Tailwind v4는 마이너 업데이트가 아니에요. 완전히 새로 만들어졌어요. Rust로 엔진을 새로 짰고, 설정 방식도 완전히 바뀌었고, PostCSS 플러그인은 이제 없어요. 업그레이드 미루고 계셨다면 이 글 보고 따라하시면 돼요.
프로덕션 앱 3개를 업그레이드해봤는데요: 삽질할 가치가 있어요. 빌드 시간이 3-10배 빨라지고, CSS 용량도 줄고, 새 설정 방식도 익숙해지면 오히려 편해요.
뭐가 바뀌었고 각각 어떻게 마이그레이션하는지 정리해볼게요.
뭐가 바뀌었나요?
마이그레이션 전에 큰 그림부터 알아야 해요:
1. Rust로 새로 만든 엔진 (Oxide)
v3는 JS 엔진이었는데요, v4는 Rust로 만든 Oxide 엔진을 써요. 그냥 빠른 게 아니라 진짜 다른 레벨이에요:
| 항목 | v3 | v4 | 개선 |
|---|---|---|---|
| 첫 빌드 | ~800ms | ~100ms | 8배 빠름 |
| 증분 리빌드 | ~200ms | ~5ms | 40배 빠름 |
| CSS 출력 크기 | 24KB | 18KB | 25% 작아짐 |
Rust라서 병렬 처리도 잘 되고 메모리도 덜 먹어요. 개발할 때 HMR이 이제 진짜 즉시 반영돼요.
2. 설정이 CSS로 이동했어요
이게 제일 큰 변화예요. v3에서는 tailwind.config.js에서 다 설정했잖아요:
// v3: tailwind.config.js module.exports = { theme: { extend: { colors: { primary: '#3b82f6', secondary: '#10b981', }, fontFamily: { sans: ['Inter', 'sans-serif'], }, }, }, }
v4는 설정을 CSS 파일 안에 @theme으로 써요:
/* v4: app.css */ @import "tailwindcss"; @theme { --color-primary: #3b82f6; --color-secondary: #10b981; --font-sans: "Inter", sans-serif; }
뭐가 좋냐면:
- 설정이 스타일이랑 같이 있음
- IDE 자동완성 더 잘 됨
- DevTools에서 바로 확인 가능
- JS 설정 파일 따로 안 만들어도 됨
3. PostCSS 플러그인 없음
v3에서 Tailwind는 PostCSS 플러그인이었어요:
// v3: postcss.config.js module.exports = { plugins: { tailwindcss: {}, autoprefixer: {}, }, }
v4에서 Tailwind는 독립 CLI나 Vite 플러그인이에요. 호환성을 위해 PostCSS도 지원하지만 기본값은 아니에요:
// v4: vite.config.ts (권장) import tailwindcss from '@tailwindcss/vite' export default { plugins: [tailwindcss()], }
# v4: CLI 대안 npx @tailwindcss/cli -i input.css -o output.css --watch
4. 자동 컨텐츠 감지
v3에서 content 경로 설정하던 거 기억나시죠?
// v3: tailwind.config.js module.exports = { content: [ './src/**/*.{js,ts,jsx,tsx,mdx}', './components/**/*.{js,ts,jsx,tsx}', ], }
v4에서 Tailwind는 프로젝트를 분석해서 Tailwind 클래스를 사용하는 파일을 자동으로 감지해요. 대부분 프로젝트에서 설정 필요 없어요. 커스터마이징이 필요하면:
/* v4: 자동 감지 오버라이드 */ @import "tailwindcss"; @source "../node_modules/some-ui-library";
5. 네이티브 CSS 캐스케이드 레이어
v4는 (Tailwind의 커스텀 구현이 아닌) 네이티브 CSS @layer를 사용해요:
/* v4가 생성하는 진짜 CSS 레이어 */ @layer theme, base, components, utilities; @layer utilities { .text-primary { color: var(--color-primary); } }
이렇게 하면 캐스케이드 제어가 제대로 되고 다른 CSS와의 통합도 좋아져요.
마이그레이션 따라하기
자, 이제 진짜 해볼게요. React/Next.js 프로젝트 기준으로 정리했어요.
1단계: 디펜던시 업데이트
기존 Tailwind 패키지 제거하고 v4 설치:
# v3 패키지 제거 npm uninstall tailwindcss postcss autoprefixer # v4 설치 npm install tailwindcss@latest # Vite 사용하면 플러그인 추가 npm install @tailwindcss/vite # Next.js 사용하면 PostCSS 호환 패키지 추가 npm install @tailwindcss/postcss
2단계: 빌드 설정 업데이트
Vite 프로젝트:
// vite.config.ts import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [ react(), tailwindcss(), ], })
Next.js 프로젝트:
Next.js 15+는 Tailwind v4를 기본 지원해요. 이전 버전은:
// postcss.config.js (Next.js 호환) module.exports = { plugins: { '@tailwindcss/postcss': {}, }, }
독립 CLI:
# package.json scripts에 추가 "scripts": { "css:build": "npx @tailwindcss/cli -i src/input.css -o dist/output.css", "css:watch": "npx @tailwindcss/cli -i src/input.css -o dist/output.css --watch" }
3단계: CSS 진입점 변환
여기서 대부분의 작업이 이루어져요. 메인 CSS 파일을 다시 작성해야 해요.
이전 (v3):
/* globals.css */ @tailwind base; @tailwind components; @tailwind utilities; /* 아래에 커스텀 스타일 */ .btn-primary { @apply bg-blue-500 text-white px-4 py-2 rounded; }
이후 (v4):
/* globals.css */ @import "tailwindcss"; /* 커스텀 스타일 - 이제 @layer 제대로 사용 */ @layer components { .btn-primary { @apply bg-blue-500 text-white px-4 py-2 rounded; } }
핵심 변경:
@tailwind base/components/utilities→@import "tailwindcss"- 커스텀 컴포넌트 클래스는
@layer components로 감싸기 - 유틸리티 오버라이드는
@layer utilities에
4단계: tailwind.config.js를 @theme으로 마이그레이션
이게 가장 까다로운 부분이에요. JavaScript 설정을 CSS 커스텀 프로퍼티로 변환해야 해요.
이전 (v3 설정):
// tailwind.config.js module.exports = { theme: { extend: { colors: { primary: { 50: '#eff6ff', 100: '#dbeafe', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', }, accent: '#f59e0b', }, spacing: { '18': '4.5rem', '88': '22rem', }, fontSize: { 'xxs': '0.625rem', }, borderRadius: { '4xl': '2rem', }, fontFamily: { sans: ['Inter', 'system-ui', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'], }, screens: { 'xs': '475px', '3xl': '1920px', }, }, }, }
이후 (v4 @theme):
/* globals.css */ @import "tailwindcss"; @theme { /* 색상은 --color-* 접두사 */ --color-primary-50: #eff6ff; --color-primary-100: #dbeafe; --color-primary-500: #3b82f6; --color-primary-600: #2563eb; --color-primary-700: #1d4ed8; --color-accent: #f59e0b; /* 스페이싱은 --spacing-* 접두사 */ --spacing-18: 4.5rem; --spacing-88: 22rem; /* 폰트 사이즈는 --text-* 접두사 */ --text-xxs: 0.625rem; /* 보더 라디우스는 --radius-* 접두사 */ --radius-4xl: 2rem; /* 폰트 패밀리는 --font-* 접두사 */ --font-sans: "Inter", system-ui, sans-serif; --font-mono: "JetBrains Mono", monospace; /* 브레이크포인트는 --breakpoint-* 접두사 */ --breakpoint-xs: 475px; --breakpoint-3xl: 1920px; }
변수 네이밍 치트시트
| v3 설정 키 | v4 CSS 변수 접두사 | 예시 |
|---|---|---|
colors | --color-* | --color-primary-500 |
spacing | --spacing-* | --spacing-18 |
fontSize | --text-* | --text-xxs |
fontFamily | --font-* | --font-sans |
fontWeight | --font-weight-* | --font-weight-medium |
lineHeight | --leading-* | --leading-relaxed |
letterSpacing | --tracking-* | --tracking-wide |
borderRadius | --radius-* | --radius-4xl |
borderWidth | --border-* | --border-3 |
boxShadow | --shadow-* | --shadow-soft |
screens | --breakpoint-* | --breakpoint-xs |
zIndex | --z-* | --z-dropdown |
opacity | --opacity-* | --opacity-15 |
5단계: 플러그인 처리
대부분의 v3 플러그인은 업데이트가 필요하거나 코어에 흡수됐어요.
Typography 플러그인:
npm install @tailwindcss/typography@latest
/* v4: CSS에서 플러그인 임포트 */ @import "tailwindcss"; @plugin "@tailwindcss/typography";
Forms 플러그인:
npm install @tailwindcss/forms@latest
@import "tailwindcss"; @plugin "@tailwindcss/forms";
Container Queries 플러그인:
이제 코어에 내장됐어요! 플러그인 필요 없음:
<!-- v4에서 네이티브로 작동 --> <div class="@container"> <div class="@md:grid-cols-2">...</div> </div>
6단계: 폐기된 유틸리티 업데이트
일부 유틸리티는 이름이 바뀌거나 변경됐어요:
| v3 클래스 | v4 클래스 | 참고 |
|---|---|---|
bg-opacity-50 | bg-blue-500/50 | 불투명도 수정자 문법 |
text-opacity-75 | text-gray-900/75 | 같은 패턴 |
decoration-slice | box-decoration-slice | 이름 변경 |
decoration-clone | box-decoration-clone | 이름 변경 |
overflow-ellipsis | text-ellipsis | 이름 변경 |
flex-grow-0 | grow-0 | 간소화 |
flex-shrink | shrink | 간소화 |
불투명도 수정자가 이제 표준이에요:
<!-- v3 --> <div class="bg-blue-500 bg-opacity-50">...</div> <!-- v4 --> <div class="bg-blue-500/50">...</div>
7단계: 다크 모드 업데이트
다크 모드는 같은 방식으로 작동하지만 설정이 이동했어요:
/* v4: 클래스 기반 다크 모드 활성화 */ @import "tailwindcss"; @variant dark (&:where(.dark, .dark *));
또는 기본값(prefers-color-scheme) 사용:
/* 이게 기본값 - 설정 필요 없음 */ @import "tailwindcss";
흔한 마이그레이션 문제와 해결책
여러 프로젝트를 마이그레이션하면서 겪을 문제들이에요:
문제 1: "Unknown at-rule @tailwind"
에디터/린터가 아직 v3 문법을 기대하고 있어요.
해결: CSS 파일을 @import "tailwindcss"로 업데이트하세요.
문제 2: 커스텀 색상이 안 됨
증상: 마이그레이션 후 bg-primary-500이 안 먹힘.
해결: 색상 변수가 정확한 명명 규칙을 따르는지 확인하세요:
/* 틀림 */ --primary-500: #3b82f6; /* 맞음 */ --color-primary-500: #3b82f6;
문제 3: Next.js에서 PostCSS 에러
증상: PostCSS 관련 에러로 빌드 실패.
해결: 호환 패키지를 쓰고 있는지 확인하세요:
npm install @tailwindcss/postcss
// postcss.config.js module.exports = { plugins: { '@tailwindcss/postcss': {}, }, }
문제 4: 플러그인이 안 됨
증상: Typography나 forms 플러그인 클래스가 안 먹힘.
해결: 플러그인은 이제 config가 아닌 CSS로 로드해요:
@import "tailwindcss"; @plugin "@tailwindcss/typography"; @plugin "@tailwindcss/forms";
문제 5: 특정 파일에서 클래스 감지 누락
증상: 특정 파일의 클래스가 CSS를 생성 안 함.
해결: @source로 경로를 명시적으로 포함하세요:
@import "tailwindcss"; @source "../node_modules/@your-company/ui-kit/src"; @source "./content/**/*.mdx";
문제 6: IDE가 새 문법을 못 앎
해결: VS Code Tailwind CSS IntelliSense 익스텐션을 최신 버전으로 업데이트하세요. @theme과 @plugin 포함해서 v4 문법을 완전히 지원해요.
성능 비교: 실제 숫자
프로덕션 Next.js 앱(500개 이상 컴포넌트)에서 측정한 결과예요:
| 항목 | v3.4 | v4.0 | 변화 |
|---|---|---|---|
| 콜드 빌드 | 12.3초 | 1.8초 | 85% 빨라짐 |
| 개발 서버 시작 | 4.2초 | 0.8초 | 81% 빨라짐 |
| HMR 업데이트 | 340ms | 12ms | 96% 빨라짐 |
| 프로덕션 CSS | 48KB | 31KB | 35% 작아짐 |
| 메모리 사용량 | 180MB | 45MB | 75% 감소 |
Oxide 엔진이 진짜 그만큼 빨라요. 큰 코드베이스라면 성능만으로도 업그레이드 가치가 있어요.
마이그레이션 체크리스트
마이그레이션할 때 이 체크리스트 쓰세요:
- 디펜던시 업데이트 (
tailwindcss@latest, 기존 패키지 제거) - 통합 방식 선택: Vite 플러그인, PostCSS, 또는 CLI
-
@tailwind디렉티브를@import "tailwindcss"로 변환 -
tailwind.config.js테마를 CSS의@theme으로 이동 - 플러그인을
@plugin문법으로 업데이트 - 불투명도 클래스를 수정자 문법으로 변환 (
/50) - 이름 바뀐 유틸리티 업데이트
- 클래스 전략 쓰면 다크 모드 설정
- 비표준 콘텐츠 경로에
@source추가 - 모든 페이지/컴포넌트에서 시각적 리그레션 테스트
- VS Code 익스텐션 업데이트
- 다 확인 후 기존 설정 파일 제거
업그레이드해야 할까?
지금 업그레이드하세요:
- 빌드 시간이 고통스럽다면 (v4는 5-10배 빠름)
- 더 작은 CSS 번들을 원한다면
- 새 프로젝트를 시작한다면
- CSS 우선 설정 방식이 좋다면
기다리세요:
- 아직 업데이트 안 된 플러그인에 크게 의존한다면
- 중요한 릴리스 중간에 있다면
- tailwind.config.js에 복잡한 프로그래매틱 로직이 있다면
대부분 프로젝트에서 업그레이드는 설정 복잡도에 따라 1-4시간 걸려요. 성능 향상은 진짜예요—Tailwind v4는 최근 몇 년간 해본 CSS 프레임워크 업그레이드 중 가장 매끄러웠어요.
마무리
Tailwind CSS v4는 꽤 큰 업그레이드예요—새 엔진, 새 설정 방식, 새 기본값. @theme을 쓰는 CSS 방식이 처음엔 어색한데 쓰다 보면 이게 더 맞는 것 같아요. DevTools에서 바로 확인되고, IDE 지원도 좋아지고, CSS 파일이 진짜 single source of truth가 돼요.
Oxide 엔진 성능 향상은 마케팅이 아니에요. 핫 리로드가 진짜 즉시예요. 콜드 빌드가 진짜 5-10배 빨라요. 큰 프로젝트라면 이것만으로도 마이그레이션 가치가 있어요.
간단한 프로젝트로 먼저 연습하고 메인 코드베이스 건드리세요. 복잡한 거 아니에요—그냥 다를 뿐이에요.
즐거운 스타일링 되세요!
관련 도구 둘러보기
Pockit의 무료 개발자 도구를 사용해 보세요