컴포넌트 스타일링의 여러 방법(인라인, CSS Module, Tailwind, 조건부)과 각각의 장단점, 그리고 실무에서 선택 기준을 배웁니다.
🎨 리액트 스타일링 — 4가지 방법 비교
리액트에서 컴포넌트를 스타일링하는 방법은 여러 가지가 있습니다. 각각 특성과 쓰임새가 다르므로, 모두 알고 상황에 맞게 선택할 수 있어야 합니다.
1️⃣ 인라인 스타일 (Inline Styles)
JSX의 style 속성에 객체를 직접 전달하는 방식입니다.
function ColorBox({ color }: { color: string }) {
return (
<div
style={{
backgroundColor: color, // camelCase!
width: 100, // 숫자는 px 자동 적용
height: 100,
borderRadius: '8px', // 문자열엔 단위 포함
}}
/>
)
}
인라인 스타일의 CSS 속성명은 카멜케이스로 씁니다(background-color → backgroundColor). 장점은 동적 값(변수)을 바로 사용할 수 있다는 것입니다. 단점은 CSS 선택자, 미디어 쿼리, 가상 클래스(:hover)를 쓸 수 없고 성능도 떨어집니다. 간단한 동적 스타일에만 사용하세요.
2️⃣ CSS Modules
파일명이 .module.css인 CSS 파일은 클래스명이 자동으로 고유하게 변환됩니다. 전역 클래스명 충돌이 없습니다.
/* Button.module.css */
.button {
padding: 8px 16px;
background: #4f46e5;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
.button:hover {
background: #4338ca;
}
// Button.tsx
import styles from './Button.module.css'
function Button({ children }: { children: React.ReactNode }) {
return (
<button className={styles.button}>
{children}
</button>
)
}
실제 HTML에서는 Button_button__xK2j1 같은 고유 클래스로 변환됩니다. 기존 CSS의 모든 기능을 사용할 수 있고 스코프가 컴포넌트에 한정됩니다. 단, 클래스 조합이 많아지면 코드가 복잡해집니다.
3️⃣ Tailwind CSS (현재 가장 인기)
유틸리티 클래스를 조합하는 방식입니다. 별도 CSS 파일 없이 JSX 안에서 스타일을 완결합니다.
function Card({ title, description }: { title: string; description: string }) {
return (
<div className="bg-white rounded-2xl shadow-sm border border-gray-100 p-6 hover:shadow-md transition-shadow">
<h3 className="text-lg font-bold text-gray-900 mb-2">{title}</h3>
<p className="text-sm text-gray-500 leading-relaxed">{description}</p>
</div>
)
}
Tailwind의 가장 큰 장점은 JS 변수를 클래스명에 직접 삽입하기 쉽다는 것입니다. 다만 클래스 목록이 길어질 수 있어 cn() 함수(clsx + tailwind-merge)와 함께 씁니다.
🔀 조건부 클래스 적용
상태에 따라 다른 클래스를 적용해야 할 때가 많습니다. 문자열 조합 또는 라이브러리를 사용합니다:
// 단순한 경우 — 템플릿 리터럴
function Button({ variant }: { variant: 'primary' | 'secondary' }) {
const baseClass = 'px-4 py-2 rounded-lg font-medium'
const variantClass = variant === 'primary'
? 'bg-indigo-600 text-white'
: 'bg-gray-100 text-gray-700'
return <button className={`${baseClass} ${variantClass}`}>버튼</button>
}
// clsx 라이브러리 사용 (더 편리)
import clsx from 'clsx'
function Badge({ active }: { active: boolean }) {
return (
<span
className={clsx(
'px-2 py-0.5 rounded-full text-xs font-bold',
active ? 'bg-green-100 text-green-700' : 'bg-gray-100 text-gray-500'
)}
>
{active ? '활성' : '비활성'}
</span>
)
}
📊 언제 무엇을 쓸까
| 방법 | 추천 상황 | 피해야 할 상황 |
|---|---|---|
| 인라인 스타일 | 동적 값(위치, 색상 변수) | 정적 스타일, hover |
| CSS Modules | 복잡한 애니메이션, 기존 CSS 팀 | 동적 클래스가 많을 때 |
| Tailwind CSS | 빠른 개발, 디자인 시스템 없을 때 | 고도로 커스텀된 디자인 |
현재 리액트 생태계에서는 Tailwind CSS가 압도적으로 많이 쓰입니다. shadcn/ui, 대부분의 오픈소스 컴포넌트 라이브러리가 Tailwind 기반입니다.
✅ 정리
- 인라인: 동적 값에 간단히 사용, CSS 선택자 불가.
- CSS Modules: 클래스 충돌 없는 전통적 CSS,
.module.css파일 사용. - Tailwind: 유틸리티 클래스 조합, 현재 가장 인기있는 방식.
- 조건부 클래스는 템플릿 리터럴 또는
clsx라이브러리로 깔끔하게 처리합니다.
관련 주제
- 제어 컴포넌트
- value onChange
- 여러 입력 필드 관리
- 폼 제출 처리
- 개발·프로그래밍
- 개발·프로그래밍 강의
- 리액트 입문 — 컴포넌트로 만드는 웹
- 무료강의
- 무료 온라인 강의
- NUGUNA
- 누구나
댓글
불러오는 중...
