Tailwind에서 동적 변수로 클래스 만들면 왜 안 될까?

Tailwind CSS를 처음 쓰면 누구나 한 번쯤 겪는 문제입니다. (내 얘기…)

방금 겪은 문제 상황

const ORANGE = "#FF5733";
const ORANGE_CLASS= "text-[#FF5733]"

// ❌ 색상이 안 나옴!
<span className={`text-[${ORANGE}]`}>Chat</span>

// ⭕ 색상이 자잘 나옴
<span className={ORANGE_CLASS}>Chat</span>

분명히 Tailwind 문서에는 text-[#FF5733] 이렇게 쓰면 된다고 했는데…
왜 변수를 넣으면 안 될까요?


결론부터 말하면

Tailwind은 코드를 “실행”하지 않고 “텍스트로 읽기”만 합니다.

변수 ${ORANGE}가 #FF5733으로 바뀌는 건 JavaScript가 실행될 때인데,
Tailwind은 그 전에 이미 CSS를 만들어버립니다.


실제로 무슨 일이 일어날까?

npm run dev로 개발 서버를 실행하고 파일을 저장하면:

(1) PostCSS (Tailwind CSS) 처리를 먼저 진행한 후
(2) Babel (Javascript Compiler)이 변수, 템플릿 리터럴 (`)을 처리함

~> 변수를 문자열로 바꾸는 (2)번이 실행 되기 전에
(1) Tailwind CSS 처리하는 로직이 작동되기 때문에
해석이 안 되어서 색상 코드 적용이 안 됨

1단계: Tailwind이 파일을 스캔

파일 내용: className={`text-[${ORANGE}]`}
                           ↑
         Tailwind: "이게 뭐지? 색상코드 아닌데... 무시!"

2단계: CSS 생성

/* text-[#FF5733]에 대한 CSS가 안 만들어짐! */

3단계: JavaScript 실행 (브라우저)

${ORANGE} → #FF5733 으로 변환됨
결과: class="text-[#FF5733]"

4단계: 브라우저가 스타일 적용 시도

브라우저: "text-[#FF5733] 클래스의 CSS 어딨지?"
        → 없음!
        → 스타일 적용 안 됨 ❌

시간 순서가 핵심!

순서 단계 상태
1 Tailwind 스캔 ${ORANGE} (아직 변수 그대로)
2 CSS 생성 해당 클래스 없음
3 JS 실행 #FF5733으로 변환됨
4 브라우저 CSS 없어서 적용 불가 ❌

Tailwind이 먼저, JavaScript가 나중!
순서가 맞지 않아서 문제가 생깁니다.


왜 Tailwind이 먼저 실행될까?

Next.js 빌드 파이프라인 순서 때문입니다:

1. PostCSS (Tailwind 포함)
   → CSS 파일들 처리
   → 소스코드 스캔해서 클래스 수집
   → 최종 CSS 생성

        ↓

2. Babel / SWC (JavaScript 컴파일러)
   → JSX → JavaScript 변환
   → 변수, 템플릿 리터럴 처리

        ↓

3. 번들링 (Webpack / Turbopack)
   → 모든 파일 합치기

CSS는 JavaScript 실행 결과를 몰라도 만들 수 있어야 하고,
미리 만들어놔야 페이지 로딩이 빠르기 때문에 이 순서로 동작합니다.


해결 방법

방법 1: 그냥 직접 쓰기

// 가장 간단한 방법
<span className="text-[#FF5733]">Chat</span>

방법 2: 인라인 스타일 사용

const ORANGE = "#FF5733";

<span style={{ color: ORANGE }}>Chat</span>

방법 3: 전체 클래스를 변수에 저장

// 전체 문자열이 코드에 보이면 OK
const orangeText = "text-[#FF5733]";

<span className={orangeText}>Chat</span>

방법 4: Tailwind 기본 색상 사용

<span className="text-orange-500">Chat</span>

이것도 안 됩니다!

// ❌ 클래스 이름 조합
const color = "red";
<div className={`bg-${color}-500`} />

// ❌ 조건부 클래스 조합
const size = "lg";
<div className={`text-${size}`} />

Tailwind은 bg-red-500text-lg라는 완전한 문자열을 봐야 합니다.


조건부 스타일은 이렇게!

// ✅ 전체 클래스를 조건부로 선택
<div className={isActive ? "bg-red-500" : "bg-gray-500"} />

// ✅ 객체로 매핑
const colors = {
  red: "bg-red-500",
  blue: "bg-blue-500",
};
<div className={colors[selectedColor]} />

정리

방식 작동 여부
text-[#FF5733]
`text-[${변수}]`
style={{ color: 변수 }}
조건 ? "클래스A" : "클래스B"

핵심: Tailwind은 텍스트만 읽는다!


참고 자료

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다