React UI에는 조건부 className을 합치는 작은 cn() 헬퍼가 자주 필요해. 단순 연결과 충돌 해결이 왜 다른 문제인지 알아보자.
cn()이 해결하는 두 가지 문제
- 조건부 클래스: 기본 클래스에 특정 prop이 켜졌을 때만 클래스를 더하고 싶을 수 있어. 이런 조건이 늘어나면 단순 템플릿 리터럴은 금방 읽기 어려워져.
- 호출자의 재정의:
Button이 내부에서px-4를 쓰는데 호출자가px-6를 넘기면 DOM에는 두 클래스가 모두 남아. CSS가 로드된 순서에 따라 예상과 다른 값이 적용될 수 있어.
두 라이브러리의 역할
- clsx: 문자열, 배열, 조건부 객체를 받아 적용할 클래스만 공백으로 이어 줘.
- tailwind-merge: Tailwind 유틸리티의 의미를 알고 충돌하는 클래스를 정리해. 예를 들어
px-4와px-6를 함께 받으면 뒤의px-6만 남겨.
두 함수를 합친 cn()을 프로젝트의 공용 헬퍼로 두면 조건 조합과 Tailwind 충돌 해결을 한곳에서 처리할 수 있어.
cn()을 둘 자리
src/lib/cn.ts에 한 번 만들고 모든 컴포넌트에서 가져다 써. cwkPippa가 tailwind-merge를 사용하는 이유도 같아. 채팅 UI, 사이드바, council, admin 패널이 하나의 cn() 계약을 공유하면 각 컴포넌트가 문자열 병합 규칙을 다시 만들 필요가 없어.
클래스 문자열을
+나 템플릿 리터럴로 계속 이어 붙이고 있다면 cn()을 다시 만들고 있는 셈이야. 두 라이브러리는 작고 역할이 분명해. 한 번 조합한 공용 헬퍼를 두고 다음 문제로 넘어가.두 라이브러리의 책임이 달라
clsx는 조건에 따라 문자열을 골라 합치고, tailwind-merge는 px-4 px-8처럼 같은 역할의 Tailwind 유틸리티가 충돌할 때 뒤의 값을 남겨. cn()은 두 단계를 한 함수로 묶어.