모든 블로그 포스트
개발 노하우2023-07-22 (토요일)

TailwindCSS 성능 최적화 기법

정디자인6분 읽기
TailwindCSS 성능 최적화 기법

TailwindCSS 성능 최적화 기법

TailwindCSS는 직관적인 유틸리티 클래스를 통해 빠른 UI 개발을 가능하게 하지만, 대규모 프로젝트에서는 성능 이슈가 발생할 수 있습니다. 이 글에서는 TailwindCSS의 성능을 최적화하는 방법과 모범 사례를 알아봅니다.

번들 크기 최적화

1. PurgeCSS 올바르게 설정하기

TailwindCSS는 기본적으로 많은 유틸리티 클래스를 생성합니다. 프로덕션 빌드에서는 사용하지 않는 클래스를 제거하는 것이 중요합니다:

// tailwind.config.js
module.exports = {
  content: [
    './src/**/*.{js,jsx,ts,tsx}',
    './public/index.html',
  ],
  // ...
}

모든 콘텐츠 소스를 포함해야 하며, 동적으로 생성되는 클래스 이름의 경우 다음과 같이 패턴을 지정할 수 있습니다:

// tailwind.config.js
module.exports = {
  content: {
    files: ['./src/**/*.{js,jsx,ts,tsx}'],
    safelist: [
      'bg-red-500',
      'text-3xl',
      /^btn-/,  // btn- 으로 시작하는 모든 클래스
    ],
  },
  // ...
}

2. JIT(Just-In-Time) 모드 활성화

Tailwind CSS v3부터는 JIT 모드가 기본으로 활성화되어 있습니다. 이 모드는 필요한 유틸리티만 실시간으로 생성하여 개발 환경에서의 성능을 향상시킵니다:

// tailwind.config.js (v2)
module.exports = {
  mode: 'jit',
  // ...
}

코드 구성 최적화

1. 커스텀 컴포넌트 활용하기

반복적인 Tailwind 클래스 조합은 컴포넌트로 추출하여 재사용성을 높이고 코드 중복을 줄입니다:

// 중복된 클래스 사용
function App() {
  return (
    <div>
      <button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
        버튼 1
      </button>
      <button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
        버튼 2
      </button>
    </div>
  );
}

// 컴포넌트로 추출
function Button({ children }) {
  return (
    <button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
      {children}
    </button>
  );
}

2. @apply 지시문 사용하기

자주 사용하는 클래스 조합은 @apply 지시문을 사용하여 CSS로 추출할 수 있습니다:

/* styles.css */
.btn {
  @apply px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600;
}

그러나 @apply의 과도한 사용은 Tailwind의 장점을 줄일 수 있으므로 신중하게 사용해야 합니다.

런타임 성능 최적화

1. 조건부 클래스 결합 최적화

조건부 클래스를 효율적으로 결합하려면 clsx나 classnames 같은 라이브러리를 사용하세요:

import clsx from 'clsx';

function Button({ primary, disabled }) {
  return (
    <button
      className={clsx(
        'px-4 py-2 rounded',
        primary ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-800',
        disabled && 'opacity-50 cursor-not-allowed'
      )}
    >
      버튼
    </button>
  );
}

2. 동적 클래스 생성 최소화

렌더링 성능을 위해 동적으로 클래스 문자열을 생성하는 작업을 최소화하세요:

// 좋지 않은 방식
function BadComponent({ size }) {
  // 매 렌더링마다 문자열 생성
  const sizeClass = `text-${size}`;
  return <div className={sizeClass}>텍스트</div>;
}

// 더 나은 방식
function GoodComponent({ size }) {
  // 미리 정의된 매핑 사용
  const sizeClasses = {
    sm: 'text-sm',
    md: 'text-md',
    lg: 'text-lg',
  };
  return <div className={sizeClasses[size]}>텍스트</div>;
}