이 글은 누구를 위한 것인가
- Tailwind CSS v4의 변경사항을 파악하고 마이그레이션을 계획하는 팀
@theme으로 디자인 토큰을 관리하고 싶은 개발자- CSS-first 설정으로
tailwind.config.js없이 Tailwind를 설정하려는 팀
들어가며
Tailwind CSS v4는 설정 방식을 완전히 바꿨다. JavaScript 설정 파일 대신 CSS 파일에서 @theme으로 설정하고, @import 'tailwindcss' 한 줄로 시작한다. LightningCSS 기반으로 빌드 속도가 5-10배 빨라졌다.
이 글은 bluefoxdev.kr의 Tailwind v4 완전 가이드 를 참고하여 작성했습니다.
1. Tailwind v4 핵심 변경사항
[v3 vs v4 비교]
설정 파일:
v3: tailwind.config.js (JS 파일)
v4: CSS 파일 내 @theme (JS 불필요)
콘텐츠 감지:
v3: content: ['./src/**/*.tsx'] 명시
v4: 자동 감지 (설정 불필요)
임포트:
v3: @tailwind base; @tailwind components; @tailwind utilities;
v4: @import 'tailwindcss'; (한 줄)
빌드 엔진:
v3: PostCSS + autoprefixer
v4: LightningCSS (5-10x 빠름)
새 유틸리티:
text-shadow-*: 텍스트 그림자
mask-image-*: 마스크 이미지
interpolate-size: 높이 애니메이션
starting-style: 마운트 애니메이션
CSS 변수:
v3: var(--tw-color-blue-500) (없음, 직접 접근 불가)
v4: var(--color-blue-500) (모든 토큰 CSS 변수로 노출)
2. Tailwind v4 설정과 마이그레이션
/* app/globals.css - v4 설정 */
@import 'tailwindcss';
/* @theme: 디자인 토큰 정의 (v3의 tailwind.config.js 대체) */
@theme {
/* 색상 */
--color-brand-50: oklch(97% 0.01 260);
--color-brand-500: oklch(55% 0.18 260);
--color-brand-900: oklch(25% 0.10 260);
/* 폰트 */
--font-sans: 'Pretendard Variable', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* 간격 오버라이드 */
--spacing-18: 4.5rem;
--spacing-22: 5.5rem;
/* 반응형 브레이크포인트 */
--breakpoint-xs: 480px;
--breakpoint-3xl: 1920px;
/* 애니메이션 */
--animate-wiggle: wiggle 0.3s ease-in-out infinite;
/* 그림자 */
--shadow-glow: 0 0 20px oklch(55% 0.18 260 / 50%);
}
/* 커스텀 애니메이션 */
@keyframes wiggle {
0%, 100% { transform: rotate(-3deg); }
50% { transform: rotate(3deg); }
}
/* 커스텀 유틸리티 */
@utility scrollbar-hide {
scrollbar-width: none;
&::-webkit-scrollbar { display: none; }
}
/* 미디어 쿼리 변형 */
@variant dark (&:is(.dark *));
@variant hocus (&:hover, &:focus-visible);
<!-- v4 새 유틸리티 사용 -->
<!-- text-shadow (v4 신규) -->
<h1 class="text-shadow-lg text-shadow-brand-500/30">
빛나는 제목
</h1>
<!-- mask-image (v4 신규) -->
<div class="mask-image-[linear-gradient(to_bottom,black_70%,transparent)]">
페이드 아웃 콘텐츠
</div>
<!-- interpolate-size: 높이 0 → auto 애니메이션 가능 -->
<details class="[interpolate-size:allow-keywords]">
<summary>더 보기</summary>
<div class="h-0 overflow-hidden transition-[height] open:h-auto">
감춰진 콘텐츠
</div>
</details>
<!-- @starting-style 지원 (마운트 애니메이션) -->
<div class="transition-opacity starting:opacity-0">
페이드 인 요소
</div>
<!-- 임의 값 (v3와 동일) -->
<div class="mt-[17px] bg-[oklch(55%_0.18_260)] text-[clamp(1rem,3vw,2rem)]">
<!-- CSS 변수 직접 참조 (v4 신규) -->
<div class="bg-[--color-brand-500]">
테마 색상 사용
</div>
<!-- 새 컨테이너 쿼리 유틸리티 -->
<div class="@container">
<div class="@sm:grid-cols-2 @lg:grid-cols-3">
컨테이너 쿼리 반응형
</div>
</div>
// v3 → v4 마이그레이션 자동화
// npx @tailwindcss/upgrade@next
// 주요 변경 사항:
// tailwind.config.js → globals.css @theme
// v3 클래스 이름 변경:
// shadow-sm → shadow-xs
// shadow → shadow-sm
// ring-offset-* → ring-offset (통합됨)
// flex-shrink → shrink
// overflow-ellipsis → text-ellipsis
// v3 config → v4 CSS 변환 예시
// v3 tailwind.config.js:
// module.exports = {
// theme: {
// extend: {
// colors: { brand: { 500: '#6366f1' } },
// fontFamily: { sans: ['Pretendard', 'sans-serif'] },
// },
// },
// };
// v4 globals.css:
// @theme {
// --color-brand-500: #6366f1;
// --font-sans: 'Pretendard', sans-serif;
// }
/* 고급 패턴 - v4 레이어 */
/* 컴포넌트 레이어 */
@layer components {
.btn {
@apply inline-flex items-center px-4 py-2 rounded-lg font-medium;
@apply transition-colors focus-visible:outline-2 focus-visible:outline-offset-2;
}
.btn-primary {
@apply btn bg-brand-500 text-white hover:bg-brand-600;
@apply focus-visible:outline-brand-500;
}
}
/* 플러그인 없이 변형 정의 */
@variant print {
@media print {
&;
}
}
/* 사용: class="print:hidden" */
/* 다크모드: CSS 변수로 토큰 교체 */
.dark {
--color-bg: oklch(15% 0.01 260);
--color-text: oklch(95% 0.01 260);
--color-surface: oklch(20% 0.01 260);
}
/* 유틸리티 생성 */
@utility container-fluid {
width: 100%;
max-width: var(--breakpoint-2xl, 1536px);
margin-inline: auto;
padding-inline: var(--spacing-4);
}
마무리
Tailwind v4의 CSS-first 접근은 설정 복잡도를 크게 줄인다. @theme에서 CSS 변수로 정의된 모든 토큰은 var(--color-brand-500)으로 직접 접근할 수 있어 CSS와 Tailwind 사이의 경계가 사라진다. 마이그레이션은 npx @tailwindcss/upgrade 자동화 도구로 대부분의 변환이 가능하지만, 커스텀 플러그인과 임의의 구성은 수동 검토가 필요하다.