시작하기
Tailwind CSS 프로젝트를 v3에서 v4로 업그레이드하는 방법
Tailwind CSS v4.0은 프레임워크의 새로운 메이저 버전입니다. 호환성 문제를 최소화하기 위해 많은 노력을 기울였지만, 일부 업데이트는 필수적입니다. 이 가이드는 v3에서 v4로 프로젝트를 업그레이드하는 데 필요한 모든 단계를 설명합니다.
이 과정을 간소화하기 위해, 일반적인 프로젝트에서 대부분의 변경 사항을 자동으로 처리할 수 있는 마이그레이션 도구를 개발했습니다.
v3에서 v4로 프로젝트를 업그레이드하고 싶다면, 우리의 업그레이드 도구를 사용해 대부분의 작업을 자동으로 처리할 수 있습니다:
$ npx @tailwindcss/upgrade@next
대부분의 프로젝트에서 업그레이드 도구는 의존성 업데이트, 설정 파일을 CSS로 마이그레이션, 템플릿 파일 변경 사항 처리 등 전체 마이그레이션 과정을 자동화합니다.
업그레이드 도구는 Node.js 20 이상이 필요하므로, 실행 전에 환경을 업데이트했는지 확인하세요.
새로운 브랜치에서 업그레이드 도구를 실행하는 것을 권장합니다. 그런 다음 변경 사항을 꼼꼼히 검토하고 브라우저에서 프로젝트를 테스트하여 모든 변경 사항이 올바르게 적용되었는지 확인하세요. 복잡한 프로젝트에서는 몇 가지를 직접 수정해야 할 수도 있지만, 어느 쪽이든 도구가 많은 시간을 절약해 줄 것입니다.
또한 v4의 주요 변경 사항을 모두 살펴보고 변경된 내용을 잘 이해하는 것도 좋은 생각입니다. 업그레이드 도구가 잡아내지 못한 프로젝트 내 다른 업데이트가 필요할 수 있기 때문입니다.
v3에서는 tailwindcss
패키지가 PostCSS 플러그인이었지만, v4에서는 PostCSS 플러그인이 별도의 @tailwindcss/postcss
패키지로 이동했습니다.
또한 v4에서는 import와 벤더 프리픽싱이 자동으로 처리되므로, 프로젝트에 postcss-import
와 autoprefixer
가 있다면 제거할 수 있습니다:
export default { plugins: { "postcss-import": {}, tailwindcss: {}, autoprefixer: {}, "@tailwindcss/postcss": {}, },};
Vite를 사용 중이라면, 성능 개선과 더 나은 개발자 경험을 위해 PostCSS 플러그인에서 새로운 전용 Vite 플러그인으로 마이그레이션하는 것을 권장합니다:
import { defineConfig } from "vite";import tailwindcss from "@tailwindcss/vite";export default defineConfig({ plugins: [ tailwindcss(), ],});
v4에서는 Tailwind CLI가 전용 @tailwindcss/cli
패키지로 이동했습니다. 빌드 명령어를 새로운 패키지를 사용하도록 업데이트하세요:
npx tailwindcss -i input.css -o output.cssnpx @tailwindcss/cli -i input.css -o output.css
Tailwind CSS v4.0의 주요 변경 사항을 모두 정리했습니다.
업그레이드 도구를 사용하면 대부분의 변경 사항을 자동으로 처리할 수 있으므로, 가능하다면 이 도구를 사용하는 것을 적극 권장합니다.
v4에서는 v3에서 사용했던 @tailwind
지시자 대신 일반 CSS @import
문을 사용해 Tailwind를 불러옵니다:
@tailwind base;@tailwind components;@tailwind utilities;@import "tailwindcss";
v3에서 더 이상 사용되지 않고 몇 년 동안 문서화되지 않았던 유틸리티를 제거했습니다. 다음은 제거된 항목과 그 대체 방법 목록입니다:
더 이상 사용되지 않음 | 대체 방법 |
---|---|
bg-opacity-* | bg-black/50 와 같은 투명도 수정자를 사용하세요. |
text-opacity-* | text-black/50 와 같은 투명도 수정자를 사용하세요. |
border-opacity-* | border-black/50 와 같은 투명도 수정자를 사용하세요. |
divide-opacity-* | divide-black/50 와 같은 투명도 수정자를 사용하세요. |
ring-opacity-* | ring-black/50 와 같은 투명도 수정자를 사용하세요. |
placeholder-opacity-* | placeholder-black/50 와 같은 투명도 수정자를 사용하세요. |
flex-shrink-* | shrink-* 를 사용하세요. |
flex-grow-* | grow-* 를 사용하세요. |
overflow-ellipsis | text-ellipsis 를 사용하세요. |
decoration-slice | box-decoration-slice 를 사용하세요. |
decoration-clone | box-decoration-clone 를 사용하세요. |
v4에서는 일관성과 예측 가능성을 높이기 위해 다음과 같은 유틸리티 이름을 변경했습니다:
v3 | v4 |
---|---|
shadow-sm | shadow-xs |
shadow | shadow-sm |
drop-shadow-sm | drop-shadow-xs |
drop-shadow | drop-shadow-sm |
blur-sm | blur-xs |
blur | blur-sm |
rounded-sm | rounded-xs |
rounded | rounded-sm |
outline-none | outline-hidden |
ring | ring-3 |
모든 유틸리티에 이름이 있는 값을 보장하기 위해 기본 그림자, 반경, 블러 스케일의 이름을 변경했습니다. 이전 버전과의 호환성을 위해 "bare" 버전은 여전히 작동하지만, <utility>-sm
유틸리티는 각각의 <utility>-xs
버전으로 업데이트하지 않으면 다르게 보일 수 있습니다.
이 변경 사항을 프로젝트에 적용하려면 모든 v3 유틸리티를 v4 버전으로 교체하세요:
<input class="shadow-sm" /><input class="shadow-xs" /><input class="shadow" /><input class="shadow-sm" />
이전의 outline-none
유틸리티는 실제로 outline-style: none
을 설정하지 않았고, 대신 접근성을 위해 강제 색상 모드에서 여전히 보이는 투명한 아웃라인을 설정했습니다.
이를 더 명확히 하기 위해 이 유틸리티를 outline-hidden
으로 개명하고, 실제로 outline-style: none
을 설정하는 새로운 outline-none
유틸리티를 추가했습니다.
이 변경 사항을 프로젝트에 반영하려면 outline-none
사용을 모두 outline-hidden
으로 바꾸세요:
<input class="focus:outline-none" /><input class="focus:outline-hidden" />
v3에서는 ring
유틸리티가 3px
링을 추가했습니다. v4에서는 이를 1px
로 변경하여 테두리와 아웃라인과 일관성을 유지하도록 했습니다.
이 변경 사항을 프로젝트에 반영하려면 ring
사용을 ring-3
으로 바꾸세요:
<input class="ring ring-blue-500" /><input class="ring-3 ring-blue-500" />
v3에서는 container
유틸리티에 center
와 padding
같은 여러 설정 옵션이 있었지만, v4에서는 더 이상 존재하지 않습니다.
v4에서 container
유틸리티를 커스터마이즈하려면 @utility
지시어를 사용해 확장해야 합니다:
@utility container { margin-inline: auto; padding-inline: 2rem;}
v4에서 Preflight의 기본 스타일에 몇 가지 작은 변경 사항을 적용했습니다:
v3에서는 테두리가 기본적으로 설정된 gray-200
색상을 사용했습니다. v4에서는 이를 모든 브라우저의 기본 동작과 일치하도록 currentColor
로 업데이트했습니다.
이 변경 사항을 프로젝트에 반영하려면 border
유틸리티를 사용하는 모든 곳에서 테두리 색상 유틸리티를 사용하거나, v3의 동작을 유지하기 위해 프로젝트에 다음 CSS를 추가하세요:
@layer base { *, ::after, ::before, ::backdrop, ::file-selector-button { border-color: var(--color-gray-200, currentColor); }}
v3에서는 플레이스홀더 텍스트가 기본적으로 설정된 gray-400
색상을 사용했습니다. v4에서는 이를 단순화하여 현재 텍스트 색상을 50% 투명도로 사용하도록 변경했습니다.
이 변경 사항은 눈에 띄지 않을 수도 있고, 오히려 프로젝트가 더 좋아 보일 수도 있습니다. 하지만 v3의 동작을 유지하고 싶다면, 프로젝트에 다음 CSS를 추가하세요:
@layer base { input::placeholder, textarea::placeholder { color: theme(--color-gray-400); }}
v3에서는 @layer utilities
안에 정의한 커스텀 클래스가 Tailwind에 의해 진정한 유틸리티 클래스로 인식되어 hover
, focus
, lg
와 같은 변형자(variants)와 자동으로 작동했습니다.
v4에서는 네이티브 캐스케이드 레이어를 사용하며 더 이상 @layer
at-rule을 가로채지 않기 때문에, 이를 대체하기 위해 @utility
API를 도입했습니다:
@layer utilities { .tab-4 { tab-size: 4; }}@utility tab-4 { tab-size: 4;}
커스텀 유틸리티를 등록하는 방법에 대해 더 알아보려면 커스텀 유틸리티 추가 문서를 참고하세요.
v3에서는 스택된 변형이 오른쪽에서 왼쪽으로 적용되었지만, v4에서는 CSS 문법과 더 비슷하게 보이도록 왼쪽에서 오른쪽으로 적용되도록 업데이트했습니다.
이 변경 사항을 프로젝트에 반영하려면, 프로젝트 내에서 순서에 민감한 스택된 변형의 순서를 반대로 바꿔야 합니다:
<ul class="py-4 first:*:pt-0 last:*:pb-0"><ul class="py-4 *:first:pt-0 *:last:pb-0"> <li>One</li> <li>Two</li> <li>Three</li></ul>
이러한 경우는 거의 없을 가능성이 높습니다. 직접 자식 변형(*
)과 타이포그래피 플러그인 변형(prose-headings
)이 가장 많이 사용될 가능성이 있으며, 그 경우에도 다른 변형과 함께 스택된 경우에만 해당됩니다.
v3에서는 var()
없이도 CSS 변수를 임의 값으로 사용할 수 있었습니다. 하지만 최근 CSS 업데이트로 인해 이 방식이 종종 모호해질 수 있어, v4에서는 대괄호 대신 괄호를 사용하는 새로운 구문으로 변경했습니다.
이 변경 사항을 적용하려면, 기존의 변수 단축 구문을 새로운 변수 단축 구문으로 바꾸면 됩니다.
<div class="bg-[--brand-color]"></div><div class="bg-(--brand-color)"></div>
v4에서는 hover
변형이 기본 입력 장치가 호버를 지원할 때만 적용되도록 업데이트했습니다:
@media (hover: hover) { .hover\:underline:hover { text-decoration: underline; }}
이 변경으로 인해, 터치 기기에서 탭 시 호버가 트리거되도록 사이트를 구축한 경우 문제가 발생할 수 있습니다. 이 문제가 발생한다면, 기존 구현을 사용하는 커스텀 hover
변형을 만들어 덮어쓸 수 있습니다:
@custom-variant hover (&:hover);
하지만 일반적으로 호버 기능을 사이트의 핵심 기능이 아닌 부가적인 기능으로 취급하는 것을 권장합니다. 터치 기기는 실제로 호버 기능을 사용할 수 없기 때문에, 호버에 의존하지 않는 것이 좋습니다.
v3에서는 프레임워크 내 특정 유틸리티를 완전히 비활성화할 수 있는 corePlugins
옵션이 있었습니다. 하지만 v4에서는 이 기능이 더 이상 지원되지 않습니다.
v4부터는 모든 테마 값에 CSS 변수를 포함하고 있으므로, 가능한 경우 theme()
함수 대신 이러한 변수를 사용하는 것을 권장합니다:
.my-class { background-color: theme(colors.red.500); background-color: var(--color-red-500);}
여전히 theme()
함수를 사용해야 하는 경우(예: CSS 변수가 지원되지 않는 미디어 쿼리에서), 이전의 점 표기법 대신 CSS 변수 이름을 사용해야 합니다:
@media (width >= theme(screens.xl)) {@media (width >= theme(--breakpoint-xl)) { /* ... */}
JavaScript 설정 파일은 하위 호환성을 위해 여전히 지원되지만, v4부터는 자동으로 감지되지 않습니다.
여전히 JavaScript 설정 파일을 사용해야 한다면, @config
지시자를 사용해 명시적으로 불러올 수 있습니다:
@config "../../tailwind.config.js";
v3에서는 JavaScript 기반 설정을 평평한 객체로 변환할 수 있는 resolveConfig
함수를 제공했습니다. 이 객체를 다른 JavaScript에서 사용할 수 있었습니다.
v4에서는 이 기능을 제거했습니다. 대신 생성된 CSS 변수를 직접 사용하는 것이 훨씬 간단하며, 번들 크기를 크게 줄일 수 있기 때문입니다.
예를 들어, React용으로 유명한 Motion 라이브러리는 CSS 변수 값을 사용하여 애니메이션을 적용할 수 있게 해줍니다:
<motion.div animate={{ backgroundColor: "var(--color-blue-500)" }} />
JavaScript에서 해석된 CSS 변수 값에 접근해야 한다면, getComputedStyle
을 사용하여 문서 루트에 있는 테마 변수의 값을 가져올 수 있습니다:
let styles = getComputedStyle(document.documentElement);let shadow = styles.getPropertyValue("--shadow-xl");