icon

안동민 개발노트

9장 : 스타일링과 CSS

Tailwind CSS 설정 및 사용


이전 절에서 CSS 모듈, Sass, 그리고 CSS-in-JS와 같은 다양한 스타일링 접근 방식을 살펴보았습니다. 각 방식은 고유한 장단점을 가지고 있으며, 프로젝트의 요구사항에 따라 선택됩니다. 이번 절에서는 최근 몇 년간 프론트엔드 개발 커뮤니티에서 폭발적인 인기를 얻고 있는 Tailwind CSS에 대해 알아보겠습니다.

Tailwind CSS는 유틸리티 우선(Utility-first) CSS 프레임워크로, 미리 정의된 작은 유틸리티 클래스를 HTML 마크업에 직접 적용해 스타일을 구성하는 방식입니다.

이 접근은 기존 CSS 작성 방식과 다른 패러다임을 제시하며, 빠른 개발 속도와 일관된 디자인 시스템 구축에 강점을 보입니다.

Next.js는 Tailwind CSS와의 통합을 매우 쉽고 효율적으로 지원합니다.


Tailwind CSS란 무엇인가요?

Tailwind CSS는 저수준(low-level) CSS 프레임워크입니다. btn, card와 같은 의미론적인(semantic) 클래스 이름을 미리 정의하여 제공하는 대신, flex, pt-4, text-center, rotate-90 등과 같이 CSS 속성-값 쌍에 직접 매핑되는 수많은 유틸리티 클래스를 제공합니다.

핵심 특징
  • 유틸리티 우선(Utility-first): HTML 요소에 class 속성으로 여러 개의 유틸리티 클래스를 조합하여 스타일을 만듭니다.
  • 컴파일 시점에 CSS 생성: 개발자가 사용한 유틸리티 클래스만 최종 CSS 번들에 포함되므로, 매우 작은 CSS 파일을 생성할 수 있습니다 (PurgeCSS 또는 JIT Engine 활용).
  • 높은 커스터마이징 가능성: tailwind.config.js 파일을 통해 디자인 토큰(색상, 폰트, 간격 등)을 자유롭게 확장하고 변경할 수 있습니다.
  • 반응형 디자인 내장: sm:, md:, lg: 등과 같은 접두사를 사용하여 반응형 디자인을 쉽게 구현할 수 있습니다.
  • 의사 클래스(Pseudo-classes) 지원: hover:, focus:, active: 등과 같은 접두사를 사용하여 상호작용 상태의 스타일을 직접 적용할 수 있습니다.
예시
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  버튼
</button>

위 코드는 background-color, padding, font-weight, border-radius 등 여러 CSS 속성들을 유틸리티 클래스로 조합하여 하나의 버튼을 스타일링합니다.


왜 Tailwind CSS를 사용해야 할까요? (이점)

Tailwind CSS는 다음과 같은 강력한 이점들을 제공합니다.

  • 빠른 개발 속도: CSS 파일을 오가며 클래스 이름을 고민하거나 새로 작성할 필요 없이, HTML 마크업 내에서 빠르게 스타일을 적용할 수 있습니다.
  • 일관된 디자인 시스템: 미리 정의된 유틸리티 클래스들은 팀 내에서 일관된 간격, 색상, 타이포그래피 등을 사용하도록 강제하여, 디자인 가이드를 준수하기 쉽게 만듭니다.
  • 유지보수성 향상: 컴포넌트를 복사하여 붙여넣으면 스타일까지 함께 복사되므로, CSS 모듈과 유사하게 스타일 고립의 이점을 얻을 수 있습니다. 특정 컴포넌트의 스타일 변경이 다른 컴포넌트에 영향을 줄 위험이 적습니다.
  • 작은 최종 CSS 번들 크기: 필요한 유틸리티 클래스만 최종 빌드에 포함되므로, 프로덕션 환경에서 매우 최적화된 CSS 파일을 얻을 수 있습니다.
  • 런타임 오버헤드 없음: CSS-in-JS와 달리 JavaScript 런타임에서 스타일을 생성하지 않으므로, 런타임 성능 저하가 없습니다.
  • 쉬운 반응형 디자인: 직관적인 접두사를 통해 모바일 우선(mobile-first) 또는 데스크톱 우선 반응형 디자인을 쉽게 구현할 수 있습니다.

Next.js에서 Tailwind CSS 설정 및 사용하기

Next.js는 Tailwind CSS를 위한 공식적인 설치 가이드를 제공하며, 설정 과정이 매우 간단합니다.

Next.js 프로젝트 생성 (또는 기존 프로젝트 사용): 만약 새로운 프로젝트를 시작한다면, npx create-next-app@latest 명령어를 통해 프로젝트를 생성할 때 Tailwind CSS를 포함할 것인지 묻는 질문에 Yes라고 답하면 됩니다.

npx create-next-app@latest my-app-with-tailwind
# ? Would you like to use Tailwind CSS? Yes

기존 프로젝트에 추가하는 경우 다음 단계를 따릅니다.

필요한 패키지 설치: tailwindcss, postcss, autoprefixer를 개발 의존성으로 설치합니다.

npm install -D tailwindcss postcss autoprefixer
# 또는
yarn add -D tailwindcss postcss autoprefixer

Tailwind CSS 설정 파일 생성: 다음 명령어를 실행하여 Tailwind CSS 설정 파일을 초기화합니다.

npx tailwindcss init -p

이 명령어는 프로젝트 루트에 두 개의 파일을 생성합니다.

  • tailwind.config.js: Tailwind CSS의 기본 설정을 커스터마이징할 수 있는 파일.
  • postcss.config.js: PostCSS 플러그인을 설정하는 파일 (Tailwind CSS와 Autoprefixer가 포함됨).

tailwind.config.js 설정: tailwind.config.js 파일을 열어 content 배열에 Tailwind CSS를 사용할 파일 경로를 추가합니다. 이는 Tailwind CSS가 어떤 파일들에서 유틸리티 클래스를 스캔하여 최종 CSS를 생성할지 알려주는 역할을 합니다.

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}', // src/app 디렉토리 내의 모든 파일
    './pages/**/*.{js,ts,jsx,tsx,mdx}', // pages 디렉토리 내의 모든 파일 (기존)
    './components/**/*.{js,ts,jsx,tsx,mdx}', // components 디렉토리 내의 모든 파일
  ],
  theme: {
    extend: {},
  },
  plugins: [],
};

전역 CSS 파일에 Tailwind 지시어 추가: Next.js의 전역 CSS 파일 (src/app/globals.css 또는 src/styles/globals.css 등)에 Tailwind CSS의 기본 지시어들을 추가합니다.

src/app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

/* 여기에 커스텀 전역 스타일을 추가할 수 있습니다. */
body {
  font-family: Arial, sans-serif;
}

이 지시어들은 Tailwind CSS가 생성하는 base (기본 스타일), components (컴포넌트 클래스), utilities (유틸리티 클래스)를 해당 위치에 주입하도록 합니다.

전역 CSS 파일을 Root Layout에 임포트: src/app/layout.tsx 파일에 위에서 설정한 전역 CSS 파일을 임포트합니다.

src/app/layout.tsx
import './globals.css'; // Tailwind CSS 지시어가 포함된 전역 CSS 파일 임포트

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ko">
      <body>{children}</body>
    </html>
  );
}
이제 Tailwind CSS를 사용할 준비가 완료되었습니다!

Tailwind CSS 사용 예시

이제 컴포넌트나 페이지의 JSX/TSX 파일에서 Tailwind CSS 유틸리티 클래스를 직접 사용할 수 있습니다.

실습: Tailwind CSS로 버튼과 카드 컴포넌트 스타일링
src/app/tailwind-css/page.tsx (서버 컴포넌트)
// 클라이언트 컴포넌트를 사용하기 위해 use client 지시어를 가진 파일 임포트
import TailwindButton from './TailwindButton';
import TailwindCard from './TailwindCard';

export default function TailwindCssPage() {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-100 p-8">
      <h1 className="text-4xl font-bold text-gray-800 mb-8">
        Tailwind CSS 예제
      </h1>
      <p className="text-lg text-gray-600 mb-12 text-center">
        유틸리티 클래스를 사용하여 컴포넌트를 빠르게 스타일링합니다.
      </p>

      <div className="flex flex-col md:flex-row gap-8 w-full max-w-4xl">
        {/* TailwindButton은 클라이언트 컴포넌트 */}
        <TailwindButton />

        {/* TailwindCard는 클라이언트 컴포넌트 */}
        <TailwindCard title="Tailwind 카드" description="이것은 Tailwind CSS로 스타일링된 카드 컴포넌트입니다.">
          <p className="text-gray-700">추가적인 내용입니다.</p>
          <button className="mt-4 px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors">
            자세히 보기
          </button>
        </TailwindCard>
      </div>
    </div>
  );
}
src/app/tailwind-css/TailwindButton.tsx (클라이언트 컴포넌트)
"use client";

import React, { useState } from 'react';

export default function TailwindButton() {
  const [count, setCount] = useState(0);

  return (
    <div className="flex flex-col items-center p-6 bg-white rounded-xl shadow-lg w-full md:w-1/2">
      <h2 className="text-2xl font-semibold text-gray-700 mb-4">카운터 버튼</h2>
      <p className="text-xl text-blue-600 mb-4">현재 카운트: <span className="font-bold">{count}</span></p>
      <button
        onClick={() => setCount(prev => prev + 1)}
        className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 px-6 rounded-lg shadow-md transition-all duration-300 ease-in-out transform hover:scale-105 active:scale-95"
      >
        클릭하여 카운트 증가
      </button>
      <p className="mt-4 text-sm text-gray-500">이 버튼은 클라이언트 컴포넌트에서 상태를 관리합니다.</p>
    </div>
  );
}
src/app/tailwind-css/TailwindCard.tsx (클라이언트 컴포넌트)
"use client";

import React from 'react';

interface TailwindCardProps {
  title: string;
  description: string;
  children?: React.ReactNode;
}

export default function TailwindCard({ title, description, children }: TailwindCardProps) {
  return (
    <div className="bg-white p-8 rounded-xl shadow-lg hover:shadow-xl transition-shadow duration-300 w-full md:w-1/2">
      <h2 className="text-3xl font-bold text-gray-800 mb-4">
        {title}
      </h2>
      <p className="text-gray-600 mb-6 leading-relaxed">
        {description}
      </p>
      {children}
    </div>
  );
}
실습 확인

위에서 설명한 Tailwind CSS 설치 및 설정 (tailwind.config.js, globals.css)을 완료합니다.

src/app/tailwind-css 폴더를 만들고 위 page.tsx, TailwindButton.tsx, TailwindCard.tsx 파일을 생성합니다.

개발 서버(npm run dev)를 실행한 후, http://localhost:3000/tailwind-css로 접속합니다.

  • Tailwind CSS 클래스들이 적용된 깔끔한 UI를 확인할 수 있습니다.
  • 클릭하여 카운트 증가 버튼을 눌러 상태 변화와 스타일이 잘 작동하는지 확인합니다.
  • 브라우저 개발자 도구를 열어 요소들의 클래스 목록을 확인하면, CSS-in-JS나 CSS 모듈처럼 해시값이 붙지 않고 작성된 유틸리티 클래스 이름 그대로 나타나는 것을 볼 수 있습니다.

Tailwind CSS의 장점과 고려사항

장점
  • 극강의 개발 생산성: CSS 파일을 오가지 않고 HTML/JSX 내에서 거의 모든 스타일을 구현할 수 있습니다.
  • 최적화된 CSS 번들: 사용하지 않는 CSS는 포함되지 않아 최종 빌드 파일이 매우 작습니다.
  • 일관된 디자인: 디자인 토큰을 기반으로 하므로 일관된 디자인 시스템을 자연스럽게 강제합니다.
  • 유지보수 용이: 컴포넌트의 스타일이 컴포넌트 자체에 캡슐화되어 있어, 다른 컴포넌트와의 충돌 위험이 적습니다.
고려사항
  • 긴 클래스 목록: 복잡한 컴포넌트의 경우 class 속성이 매우 길어질 수 있습니다. @apply 지시어를 사용하여 반복되는 유틸리티 클래스 묶음을 커스텀 클래스로 추상화할 수 있지만, 이는 Tailwind의 핵심 철학에서 벗어날 수 있습니다.
  • 초기 학습 곡선: 기존 CSS에 익숙한 개발자는 유틸리티 우선 방식에 적응하는 데 시간이 걸릴 수 있습니다. 모든 스타일이 클래스 이름으로 어떻게 매핑되는지 학습해야 합니다.
  • 정적 웹사이트에 강점: 동적인 스타일(런타임에 완전히 새로운 스타일 생성)에는 CSS-in-JS가 더 유리할 수 있습니다. 하지만 Tailwind도 변수나 동적 클래스 바인딩을 통해 어느 정도 동적 스타일을 처리할 수 있습니다.
  • 직접 CSS 작성의 감소: 때로는 직접 CSS를 작성해야 할 필요성을 느끼지 못하게 되어, CSS의 기본 개념에 대한 이해도가 낮아질 수 있다는 비판도 있습니다.

Tailwind CSS는 빠른 개발, 일관된 디자인 시스템, 그리고 최적화된 성능을 중시하는 프로젝트에 매우 훌륭한 선택입니다. 특히 Next.js와 함께 사용하면 설치 및 설정이 간편하여 즉시 생산성을 높일 수 있습니다. 프로젝트의 특성과 팀의 선호도에 맞춰 Tailwind CSS를 고려해 보세요.

목차