Contents
see List작성일 2025. 11. 30.
CSS-in-JS vs Tailwind CSS 비교
React 프로젝트에서 스타일링 방식 선택은 중요한 결정입니다. CSS-in-JS(styled-components, Emotion)와 Tailwind CSS의 특징, 장단점을 비교하여 프로젝트에 맞는 선택을 도와드립니다.
언제 어떤 것을 선택하나요?
- CSS-in-JS: 동적 스타일링, 컴포넌트 캡슐화 중시
- Tailwind: 빠른 개발, 일관된 디자인 시스템
CSS-in-JS 예시 (styled-components)
import styled from "styled-components";
// 기본 스타일 컴포넌트
const Button = styled.button`
padding: 10px 20px;
background-color: ${props => props.primary ? "#3498db" : "#fff"};
color: ${props => props.primary ? "#fff" : "#333"};
border: 2px solid #3498db;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.9;
}
&:disabled {
opacity: 0.5;
cursor: not-allowed;
}
`;
// 확장
const LargeButton = styled(Button)`
padding: 15px 30px;
font-size: 18px;
`;
// 사용
function App() {
return (
<>
<Button>기본</Button>
<Button primary>Primary</Button>
<LargeButton primary>Large</LargeButton>
</>
);
}Tailwind CSS 예시
// 기본 사용
function Button({ primary, children }) {
return (
<button className={`
px-5 py-2.5 rounded border-2 border-blue-500 cursor-pointer
transition-opacity hover:opacity-90
disabled:opacity-50 disabled:cursor-not-allowed
${primary
? "bg-blue-500 text-white"
: "bg-white text-gray-800"
}
`}>
{children}
</button>
);
}
// clsx/classnames로 가독성 향상
import clsx from "clsx";
function Button({ primary, size, disabled, children }) {
return (
<button
className={clsx(
"rounded border-2 border-blue-500 transition-opacity",
"hover:opacity-90 disabled:opacity-50",
{
"bg-blue-500 text-white": primary,
"bg-white text-gray-800": !primary,
"px-3 py-1.5 text-sm": size === "sm",
"px-5 py-2.5": size === "md",
"px-7 py-3 text-lg": size === "lg",
}
)}
disabled={disabled}
>
{children}
</button>
);
}비교표
| 항목 | CSS-in-JS | Tailwind |
|---|---|---|
| 학습 곡선 | 낮음 (CSS 문법) | 중간 (클래스 암기) |
| 번들 크기 | 런타임 증가 | 빌드 시 제거 (작음) |
| 동적 스타일 | 매우 좋음 | 제한적 |
| 성능 | 런타임 오버헤드 | 빠름 (순수 CSS) |
| 캡슐화 | 완벽 | 없음 |
| 디자인 일관성 | 수동 관리 | 자동 (토큰 기반) |
| IDE 지원 | 좋음 | 매우 좋음 |
| SSR | 추가 설정 | 문제 없음 |
Tailwind 장점
// 1. 일관된 스페이싱/색상 시스템
// p-4 = 1rem, p-8 = 2rem (4px 단위)
<div className="p-4 m-2 space-y-4">
// 2. 반응형이 직관적
<div className="text-sm md:text-base lg:text-lg">
// 3. 상태 변형이 간단
<button className="bg-blue-500 hover:bg-blue-600 active:bg-blue-700">
// 4. 다크모드 쉬움
<div className="bg-white dark:bg-gray-800">
// 5. @apply로 재사용
/* styles.css */
.btn-primary {
@apply px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600;
}CSS-in-JS 장점
// 1. 동적 스타일링
const Box = styled.div`
width: ${props => props.width}px;
background: ${props => props.theme.colors.primary};
`;
// 2. 테마 시스템
<ThemeProvider theme={darkTheme}>
<App />
</ThemeProvider>
// 3. CSS 기능 완전 지원
const Animation = styled.div`
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
animation: spin 1s linear infinite;
`;
// 4. 컴포넌트와 스타일 함께 관리
// Button.jsx 파일 하나에 모든 것이 있음하이브리드 접근법
// Tailwind + CSS-in-JS 조합
import styled from "styled-components";
import tw from "twin.macro";
const Button = styled.button`
${tw`px-4 py-2 rounded font-bold`}
${props => props.primary
? tw`bg-blue-500 text-white`
: tw`bg-gray-200 text-gray-800`
}
`;
// CVA (Class Variance Authority) - Tailwind용
import { cva } from "class-variance-authority";
const button = cva("px-4 py-2 rounded font-bold", {
variants: {
intent: {
primary: "bg-blue-500 text-white",
secondary: "bg-gray-200 text-gray-800",
},
size: {
sm: "text-sm",
md: "text-base",
lg: "text-lg px-6 py-3",
},
},
defaultVariants: {
intent: "primary",
size: "md",
},
});
<button className={button({ intent: "primary", size: "lg" })}>추천
- 신규 프로젝트, 빠른 개발: Tailwind CSS
- 복잡한 동적 UI, 테마: CSS-in-JS
- 대규모 팀, 디자인 시스템: Tailwind + CVA
- 기존 CSS 경험 활용: CSS Modules 또는 CSS-in-JS
javascript
| No | 작성일 | Title |
|---|---|---|
| 2921 | 2026. 05. 31. | 브라우저 중복 탭 작업 제어: BroadcastChannel과 Web Locks로 자동 저장 충돌 막기 |
| 2866 | 2026. 05. 23. | Node.js 운영 추적 로그 설계: AsyncLocalStorage로 요청 ID와 장애 원인 연결하기 |
| 2787 | 2026. 05. 15. | Node.js fetch 타임아웃·재시도 표준 패턴: AbortSignal로 장애 전파 막기 |
| 2589 | 2026. 04. 23. | ES2026 JavaScript 신기능 완전 가이드: using/await using, Array.fromAsync, Error.isError, Math.sumPrecise 실전 적용 |
| 2490 | 2026. 04. 14. | ES2025/ES2026 완벽 정리: Iterator Helpers, Temporal API, using 키워드 실전 가이드 |
| 2469 | 2026. 04. 13. | ES2026 완벽 가이드: Temporal API, using/await using, Array/Set 신기능 총정리 |
| 2449 | 2026. 04. 12. | ES2025/ES2026 JavaScript 신기능 완벽 정리: Temporal API부터 using 키워드까지 |
| 2425 | 2026. 04. 11. | Node.js 24 LTS 핵심 신기능 완벽 가이드 - V8 13.6, Permission Model, URLPattern |
| 2389 | 2026. 04. 09. | ES2025 핵심 신규 기능 총정리 - Set 연산, Iterator Helpers, Temporal API까지 |
| 2368 | 2026. 04. 08. | ES2025/ES2026 완벽 정리: Temporal API, Resource Management, 새 문법 총정리 |