오래된 사이드 프로젝트를 Tailwind v4로 올려봤다. 릴리즈 노트만 보면 "새 엔진, 빨라졌다" 정도인데, 막상 마이그레이션해보니 체감되는 변화는 설정 방식이었다. tailwind.config.js가 사실상 사라진다.
v3까지는 색상 하나 추가하려면 JS 설정 파일을 열고, theme.extend.colors에 넣고, 저장하고, 다시 CSS에서 클래스를 썼다. 설정은 JS에 있고 스타일은 CSS에 있는 이 분리가 늘 어정쩡했다. v4는 이걸 CSS 안으로 다 넣었다.
설치부터 다르다
PostCSS 플러그인 이름이 바뀌었다. 이제 @tailwindcss/postcss를 쓴다.
npm install tailwindcss @tailwindcss/postcss
// postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
autoprefixer랑 postcss-import를 따로 넣던 것도 이제 엔진이 내장으로 처리한다. Vite를 쓴다면 아예 @tailwindcss/vite 플러그인 하나로 끝난다.
@tailwind 지시어 대신 @import
CSS 진입점도 한 줄로 줄었다.
/* 예전 (v3) */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* 지금 (v4) */
@import 'tailwindcss';
설정은 이제 CSS에서
핵심이 이거다. 디자인 토큰을 @theme 블록에 CSS 변수로 선언한다.
@import 'tailwindcss';
@theme {
--color-brand: #2563eb;
--color-brand-dark: #1e40af;
--font-display: 'Pretendard', sans-serif;
--spacing-18: 4.5rem;
}
이렇게만 하면 bg-brand, text-brand-dark, font-display, p-18 클래스가 자동으로 생긴다. 변수 이름의 접두사(--color-, --font-)를 보고 Tailwind가 어떤 유틸리티를 만들지 판단한다. JS 설정 파일을 열 일이 없어졌다.
게다가 @theme로 선언한 값은 진짜 CSS 변수라서, 런타임에 그대로 참조할 수 있다. 임의 값 대신 var()를 바로 쓸 수 있다는 뜻이다.
.custom-card {
border-color: var(--color-brand);
}
content 경로 설정도 안 한다
v3에서 자주 삽질하던 content: [...] 배열도 없어졌다. v4는 프로젝트 파일을 자동으로 감지해서 클래스를 찾는다. .gitignore를 참고해서 빌드 산출물은 알아서 건너뛴다. 처음엔 "설정을 안 했는데 왜 되지?" 싶어서 오히려 불안했는데, 그냥 된다.
마이그레이션 팁
기존 프로젝트라면 공식 업그레이드 도구를 돌리는 게 가장 빠르다.
npx @tailwindcss/upgrade
tailwind.config.js를 @theme 기반 CSS로 변환하고, 바뀐 클래스명(shadow-sm → shadow-xs 같은)도 자동으로 고쳐준다. 커밋을 깨끗하게 나눠둔 상태에서 돌리고 diff를 확인하는 걸 추천한다.
정리하면, v4의 실질적인 변화는 속도보다 "설정을 CSS 한곳으로 모은 것"이다. JS 설정 파일과 CSS를 오가던 흐름이 사라지니 확실히 덜 번거롭다. 새 프로젝트라면 고민할 것 없이 v4로 시작하면 되고, 기존 프로젝트도 업그레이드 도구 덕분에 이전만큼 부담스럽지 않다.