cn : tailwind-merge 와 clsx를 결합한 유틸리티 함수
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
이런 유틸리티 함수를 찾았는데
아주 유용해 보였습니다.
그런데 이전 프로젝트에서 twMerge 함수만으로도
clsx 없이 유사하게 썼던 기억이 있어서
차이점에 대해 다시 짚어봤습니다.
결론은
위처럼 cn (이름이야뭐,,,) 함수를 쓰는 것이
clsx 의 여러 기능도 사용하면서 tailwind 유틸리티 클래스들을
효과적으로 병합할 수 있는 좋은 방법이다
였습니다.
제가 헷갈렸던 내용은
className={twMerge(
'w-6 h-6',
pathname === href ? 'text-primary-color-400' : 'text-grayscale-color-300',
)}
이런식으로 twMerge 만으로도 clsx 와 비슷하게 썼었던 기억 때문이었는데,
이건 생각해보니 그냥 당연한 것이었습니다..
twMerge 는 다음과 같은데
declare const twMerge: (...classLists: ClassNameValue[]) => string;
classList 를 위처럼 받고 있기에 삼항연산자 부분은 그냥 배열화 되어서 인자로 넘어가는 것일 뿐이었습니다.
결과적으로 twMerge 는 단순히 병합만 해주는 친구였는데,
clsx('btn', { 'btn-primary': isPrimary, 'btn-disabled': isDisabled });
예를들어 clsx에서 위처럼 객체나 배열로 여러 옵션을 주는 등의 기능은 tailwind-merge에는 없습니다.
gpt 질의응답 내역도 첨부합니다.
Q1
이렇게 함수를 만들어서 쓰면(cn), tailwind-merge 나 clsx 만 썻을때 보다 무엇이 좋은가요?
A1
이 함수는 clsx
와 tailwind-merge
를 결합하여 각각의 장점을 동시에 활용하는 방식입니다. 단일 라이브러리를 사용하는 것보다 두 라이브러리를 함께 사용할 때 얻을 수 있는 이점이 몇 가지 있습니다.
1. clsx
의 장점: 조건부 클래스 병합
clsx
는 조건부로 클래스명을 적용할 수 있는 기능을 제공합니다. 객체나 배열을 전달하여 조건에 따라 클래스를 추가하거나 제외할 수 있습니다.
예를 들어, 특정 클래스가 조건에 따라 동적으로 추가되어야 할 때 clsx
를 사용하면 가독성과 관리가 용이해집니다.
clsx('btn', { 'btn-primary': isPrimary, 'btn-disabled': isDisabled });
2. tailwind-merge
의 장점: Tailwind 클래스 중복 제거
tailwind-merge
는 중복되거나 상충되는 Tailwind 클래스를 병합하여 가장 우선되는 클래스를 남깁니다.
예를 들어, 같은 스타일의 클래스가 중복될 경우 가장 오른쪽 클래스만 유지하는 방식으로 충돌을 방지합니다.
twMerge('p-4 p-6');
// 결과: 'p-6' (p-4는 제거됨)
결합했을 때의 장점:
clsx
와 tailwind-merge
를 결합하면, 조건부 클래스 관리와 Tailwind 클래스 병합의 이점을 모두 얻을 수 있습니다.
함수로 결합했을 때 얻을 수 있는 이점:
조건부 클래스 적용과 중복 제거 동시 해결:
clsx
는 조건부로 클래스를 추가하는 데 탁월하고,tailwind-merge
는 중복되는 Tailwind 클래스들을 효율적으로 제거합니다.- 두 기능을 결합하면, 조건부로 클래스를 추가하면서도 중복된 Tailwind 클래스가 제거됩니다.
// 예시: 조건부 클래스와 중복 제거 동시 처리
const className = cn('p-4', isPrimary && 'p-6', 'text-center', isDisabled && 'opacity-50');
// 결과: 'p-6 text-center opacity-50' (중복된 p-4는 제거)
- 가독성과 유연성 증가:
- 단일 함수에서 조건부 클래스 로직과 중복 제거를 처리하므로, 코드가 더 간결하고 읽기 쉬워집니다.
- 프로젝트 규모가 커질수록 이 패턴은 유연성을 제공하며, 다양한 상황에서 효율적인 클래스 관리를 가능하게 합니다.
- 유지보수성 향상:
- 이 함수는 조건부 논리와 중복 제거라는 두 가지 중요한 기능을 한곳에서 관리하므로, 유지보수가 더 쉬워집니다.
- 코드의 일관성을 유지하면서 실수를 줄이는 데도 도움이 됩니다.
결론:
clsx
는 조건부 클래스 적용에 강점이 있고,tailwind-merge
는 Tailwind 클래스의 중복 제거에 탁월합니다.- 이 둘을 결합하면 조건부 클래스 적용과 중복 제거를 동시에 처리할 수 있어 가독성, 유연성, 유지보수성이 향상됩니다.
- 특히 Tailwind CSS와 같이 클래스가 동적으로 추가되는 상황에서는 더 직관적인 코드 작성이 가능합니다.
Q2
그런데 제 예전 프로젝트에서 아래처럼 써도 동작했었던 기억이 있어요.(twMerge 에 삼항연산자로 넘긴 내용)
A2
네, tailwind-merge
자체는 문자열들을 병합하고 중복되는 Tailwind 클래스를 처리하는 역할을 하지만, 조건부로 클래스명을 전달하는 방식도 지원합니다. 즉, 조건부 연산(삼항 연산자)를 사용해 문자열을 동적으로 전달하면, twMerge
가 그 결과로 나온 문자열들을 병합하여 처리합니다.
삼항 연산자를 사용한 조건부 클래스 명 전달은 자바스크립트 로직이므로, twMerge
내부에서 해당 로직을 직접적으로 처리하는 게 아니라, 결과적으로 전달된 문자열을 병합합니다. 이 점에서 clsx
와의 차이점이 있습니다.
예시:
className={twMerge(
'w-6 h-6',
pathname === href ? 'text-primary-color-400' : 'text-grayscale-color-300'
)}
pathname === href ? 'text-primary-color-400' : 'text-grayscale-color-300'
: 삼항 연산자를 통해 조건부로 클래스를 적용.twMerge
는 문자열을 병합하는 역할만 수행하므로, 삼항 연산자의 결과를 그대로 병합합니다.
이 방식은 자바스크립트의 조건부 연산을 사전에 처리한 뒤, twMerge
로 넘기기 때문에 twMerge
만 사용해도 조건부 클래스 적용이 가능해 보이는 것입니다.
차이점:
clsx
는 조건부 클래스 적용을 위해 객체와 배열 형태로 다양한 상황을 처리할 수 있는 추가 기능을 제공합니다.twMerge
는 단순히 전달된 문자열을 병합할 뿐이며, 조건부 로직을 자체적으로 처리하지는 않습니다. 대신, 자바스크립트 연산 결과를 병합합니다.
결론:
twMerge
는 자체적으로 조건부 클래스 적용 기능을 제공하지 않지만, 삼항 연산자나 다른 자바스크립트 연산을 통해 조건부로 문자열을 전달하면 그 결과를 병합할 수 있습니다.
'TIL' 카테고리의 다른 글
[240930 TIL] 비동기, 이벤트루프, 큐 (2) | 2024.10.02 |
---|---|
[240929 TIL] 간단정규식으로 파일명에 특정문자열 추가하기 (0) | 2024.09.29 |
[240925 TIL] ReactNode, FC(gpt 질의) (0) | 2024.09.25 |
[240924 TIL] yarn berry 관련(gpt질의) (0) | 2024.09.24 |
[240923 TIL] 모노레포 테일윈드 font 설정 (0) | 2024.09.23 |