Tailwind CSS 딥다이브Tailwind CSS 확장 프로그램 소개에 이어, 이번 글에서는 Tailwind CSS를 더 잘 쓰기 위한 라이브러리들을 알아보겠습니다.

본 가이드는 아래를 기준으로 작성되었습니다.

  • IDE: VS Code(Cursor)
  • Package Manager: pnpm
  • Tailwind CSS: v4.0

아래에서 소개될 설정 속성들은 .vscode/settings.json 파일에 추가하는 상황을 고려해 속성을 설명합니다.

이는 해당 프로젝트에 한정하여 extension들의 setting을 설정할 수 있고, 이 설정값은 같은 프로젝트를 다루는 모든 개발자들에게 공통적으로 적용됩니다. 설명의 편의를 위한 예시이므로 .vscode/settings.json 파일에 추가하는 것은 상황에 따라 구분해주시기 바랍니다.

tailwindcss는 추천 class 순서에 따라 클래스가 자동 정렬되도록 하는 공식 Prettier Plugin을 지원합니다.

tailwindcss에서 추천하는 순서에 따라 자동으로 classNames를 정렬해줍니다. 감히 필수 중의 필수인 라이브러리라고 할 수 있습니다.

우선 prettierprettier-plugin-tailwindcss를 설치합니다. -D--save-dev의 줄임말로, 개발 의존성으로 설치한다는 뜻입니다.

# bash
pnpm install -D prettier prettier-plugin-tailwindcss
 

이제 프로젝트 루트에 .prettierrc 파일을 생성하고 아래 내용을 추가합니다.

// .prettierrc
{
  "plugins": ["prettier-plugin-tailwindcss"]
}
 

  • 컴포넌트 클래스가 가장 먼저 오고, 그 다음 유틸리티 클래스가 배치됩니다.
  • 다른 클래스를 override하는 클래스가 항상 이후에 배치됩니다.
  • box model > layout에 영향을 주는 요소들로 시작 > decoration과 관련된 클래스 순서로 배치됩니다.
  • 기본 유틸리티 이후 hover:, focus:, active: 등의 클래스가 배치됩니다.
  • md:, lg: 등의 반응형 modifier가 작은 순서에서 큰 순서까지 그룹으로 배치됩니다.
  • 커스텀 클래스는 가장 처음에 배치됩니다.

정렬 순서의 자세한 예시는 How classes are sorted 문서를 참고해주세요.

tailwindcss를 사용하다 보면, className의 순서대로 override가 먹히지 않습니다. 뒤쪽에 오는 className으로 덮어 씌워져야 할 것 같은데 말이죠. 그래서 이런 문제를 해결하는 라이브러리입니다. 자세한 건 tailwind-merge - what is it for 부분을 참고해주세요.

pnpm install tailwind-merge

현재는 Tailwind v4이지만, 만약 Tailwind v3를 사용하고 계시다면 특정 버전을 사용하셔야 합니다. 문서를 참고해주세요. (참고: tailwind-merge v2.6.0)

import { twMerge } from 'tailwind-merge'
 
twMerge('px-2 py-1 bg-red-500 hover:bg-red-700', 'p-3 bg-blue-500')
// → 'hover:bg-red-700 p-3 bg-blue-500'

우리의 기대처럼 후순위에 자리한 className의 속성으로 override됩니다.

좋은 점은 tailwindcss에서 p-3px-2는 다르게 취급되는데, 예를 들면, className이 px-2 p-3이더라도 padding: 12px 8px처럼 계산될 수 있는 거죠. 하지만 tailwind-css를 사용하면 같지만 다른 유틸리티들을 사용자의 기대처럼 덮어버립니다. (참고: Allow refinements)

이 밖에도 다양한 tailwind-merge의 기능은 Features 페이지를 참고해주세요.

clsx는 공식문서의 Usage만으로도 사용의 이유를 명확히 설명할 수 있습니다.

import clsx from 'clsx';
// or
import { clsx } from 'clsx';
 
// Strings (variadic)
clsx('foo', true && 'bar', 'baz');
//=> 'foo bar baz'
 
// Objects
clsx({ foo:true, bar:false, baz:isTrue() });
//=> 'foo baz'
 
// Objects (variadic)
clsx({ foo:true }, { bar:false }, null, { '--foobar':'hello' });
//=> 'foo --foobar'
 
// Arrays
clsx(['foo', 0, false, 'bar']);
//=> 'foo bar'
 
// Arrays (variadic)
clsx(['foo'], ['', 0, false, 'bar'], [['baz', [['hello'], 'there']]]);
//=> 'foo bar baz hello there'
 
// Kitchen sink (with nesting)
clsx('foo', [1 && 'bar', { baz:false, bat:null }, ['hello', ['world']]], 'cya');
//=> 'foo bar hello world cya'

정리하면 대략 이렇습니다.

  • 다양한 타입 구성(단순 문자열, 배열, 객체, 혼합)
  • 조건적 구성 + 객체 형태 지원
  • falsy값(0, undefined, false 등) 무시
  • 강력한 nesing 구조 분해 및 평탄화(flatten) 지원

pnpm install -D clsx

참고로 코드 제공형 라이브러리로 2024년 트렌드였던 shadcn/ui는 Tailwind CSS 기반인데, 컴포넌트를 설치하면 자동으로 아래의 코드를 만들어 줍니다.

// lib/utils.ts
 
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

이 코드는 이 clsx와 앞서 소개된 twMerge를 엮어서 사용하는 방식입니다. 정리하면 아래 2가지 이점을 취하기 위함입니다.

  • tw-merge : className의 올바른 병합(merge, overriding)을 위하여
  • clsx : className의 구성 타입과 조건부 구성을 위하여

styled-components, emotion 등 css-in-js와 함께 유연하게 tailwindcss를 혼용하기 위해 사용합니다.

여기부터는 선택의 영역입니다. 저는 사용하지 않기로 선택했어요.

  • css-in-js의 경우 SSR을 지원하지 않거나 별도로 고도의 설정을 해줘야 하기 때문입니다.
  • 또한 자체 문법을 가지고 있는데, 편의성과 가독성을 가질 수 있게 되지만 그만큼 AI 친화성에서 멀어지게 됩니다.
  • Next15 등 최신 버전의 환경에서는 제대로 동작하지 않을 수 있습니다.

사용을 결정할 때 많은 포스트를 참고했습니다. 관심 있으신 분들은 아래 포스트를 참고해주세요.

여기까지 Tailwind CSS를 회사 프로젝트에서 사용하기 위한 PoC(Tailwind CSS 딥다이브)와 더 편하게 쓰기 위한 VS Code 확장 프로그램들(Tailwind CSS 확장 프로그램 소개)에 이어 라이브러리까지 알아봤어요.

다음 시리즈는 Tailwind CSS의 자체 config 설정 및 customization 방법을 정리할 계획이에요. 또한 제가 터득하거나 이미 유명한 사용 팁들을 소개해볼 계획도 있고요.

다만, 추가적인 조사와 내용 정리보다는 하루 빨리 뛰어들어야 하는 시점이 되어서 시리즈를 나눠 쉬어갈 예정입니다. 조금 더 실전에 부딪히며 알아낸 좋은 내용으로 글을 이어가겠습니다.

도움이 되길 바라겠습니다. 감사합니다.