노트

tailwind-merge와 cn()

tailwind-merge

프런트엔드#css#tooling · 연결된 개념 4개

쉽게 말하면

tailwind-merge는 같은 칸에 이름표가 두 장 붙으면 나중 것만 남기고 앞의 것을 떼어 내는 도구예요. 버튼 기본 배경이 파랑일 때 쓰는 쪽에서 빨강으로 덮으면 빨강이 확실히 이기게 해 줘요.

비유가 깨지는 곳 그냥 뒤에 붙이면 이길 것 같지만 클래스 문자열 순서가 아니라 스타일시트 선언 순서가 승부를 정해요. twMerge는 같은 속성 그룹만 지워서, p-4 px-2처럼 일부만 덮는 경우는 둘 다 남겨요.

같은 CSS 속성을 건드리는 Tailwind 클래스가 여러 개 붙었을 때, 뒤에 온 것만 남기고 앞의 것을 지워 주는 라이브러리. 컴포넌트의 기본 클래스를 사용처에서 덮어쓰는 패턴을 안전하게 만든다.

왜 필요한가

function Button({ className }) {
  return <button className={`px-4 bg-blue-500 ${className}`} />
}
<Button className="px-2 bg-red-500" />
// class="px-4 bg-blue-500 px-2 bg-red-500"

의도는 빨간 배경이지만 보장되지 않는다. 클래스 문자열 안의 순서는 캐스케이드와 상관이 없고, 모든 유틸리티는 명시도가 같으니 스타일시트에서 나중에 선언된 규칙이 이긴다. 그 순서는 Tailwind가 정하므로 px-4가 뒤에 있으면 px-2는 무시된다. 어떤 때는 되는 것처럼 보이다가 클래스 구성이 바뀌면 깨진다.

twMerge('px-4 bg-blue-500 px-2 bg-red-500') // 'px-2 bg-red-500'
twMerge('p-4 px-2')                          // 'p-4 px-2' (px만 덮음)
twMerge('rounded-md rounded-lg')             // 'rounded-lg'

twMerge는 어떤 클래스들이 같은 속성 그룹(padding, background, radius, display…)인지 알고 있어서 충돌만 정확히 지운다. DOM(Document Object Model)에도 쓸데없는 클래스가 남지 않는다.

clsx와의 역할 분담

clsx·classnames는 조건부로 클래스를 이어 붙이기만 하고 충돌은 해결하지 않는다. 그래서 둘을 합친 cn() 함수를 만들어 쓴다 → cn 유틸리티(clsx·tailwind-merge·cva)

export const cn = (...inputs) => twMerge(clsx(inputs))

동적으로 클래스를 합칠 일이 없는 프로젝트라면 굳이 필요 없다. 반대로 컴포넌트 라이브러리처럼 기본 스타일 + className 덮어쓰기가 많다면 거의 필수다. 원리는 Tailwind CSS의 빌드 방식에서 나온다.

출처: tailwind-merge

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 템플릿 리터럴 타입

    템플릿 리터럴 타입(Template Literal Types)은 문자열 리터럴 타입을 템플릿 문자열 문법으로 조합해 새 문자열 유니언을 만드는 기능이다. 유니언을 넣으면 가능한 모든 조합이 나온다.

  • CSS-in-JS와 빌드 타임 CSS

    JS(JavaScript) 안에서 스타일을 정의하고, 렌더링할 때 라이브러리가 클래스를 만들어 style 태그로 주입하는 방식. styled-components와 Emotion이 대표다. React 18 이후 서버 컴포넌트(React Server Components)·스트리밍 SSR(Streaming Server-Side Rendering)이 자리 잡으면서 런타임에 CSS를 만드는 방식은 줄고, 빌드할 때 CSS를 뽑는 방식이 늘었다(2026 기준).

  • CSS @layer

    CSS 규칙을 이름 붙인 묶음(레이어)으로 나누고, 묶음 사이의 우선순위를 명시적으로 정하는 기능. CSS Cascade Level 5 명세에서 캐스케이드에 새 단계로 들어왔고, 명시도보다 먼저 평가된다.

  • CSS 리셋

    브라우저마다 다른 기본 스타일(제목 여백, 목록 들여쓰기 등)을 지우거나 맞춰서, 같은 출발점에서 스타일링하게 하는 기법.

  • 속성 선택자와 형제 선택자

    대괄호 []로 HTML 속성을 기준으로 요소를 고르는 선택자와, +·~로 형제 관계를 따라 고르는 선택자. CSS뿐 아니라 querySelectorAll에서도 똑같이 쓴다.

보기 옵션