내가 Tailwind CSS를 선호하는 이유 - 격리, 그리고 AI
내가 Tailwind CSS를 선호하는 이유. 격리, 지속 가능성, 그리고 AI와의 궁합.

시작하며
저는 꽤 오랫동안 Tailwind CSS를 사용해왔습니다. 처음 도입했을 때 느꼈던 압도적인 생산성과 편리함 덕분에, 이제는 다른 방식으로 돌아가기 힘들 정도가 되었습니다.
하지만 여전히 많은 개발자들이 Tailwind CSS를 배척합니다. 가장 큰 이유는 역시 코드가 지저분해 보인다는 것입니다. HTML 태그 안에 수십 개의 클래스가 나열된 모습 때문입니다. 우리는 오랫동안 HTML은 구조, CSS는 스타일, JS는 동작이라는 식으로 역할을 분리하는 게 좋다고 배워왔습니다. 이런 관심사의 분리가 익숙한 상황에서 거부감이 드는 건 어찌 보면 당연해 보입니다.
그런데 소스 코드가 깔끔해 보이는 것이 유지보수가 편한 것과 같은지는 조금 더 생각해볼 필요가 있습니다. 제가 Tailwind CSS를 선호하는 이유를 공유해보려 합니다.
Global CSS의 현실적인 문제점
프로젝트 초기에는 공통 CSS 파일을 생성하고 기본 스타일을 정의하는 경우가 많습니다. h1, h2 같은 타이포그래피나, 기본 여백을 미리 전역에 선언해두면 편하기 때문입니다.
처음엔 좋습니다. 하지만 프로젝트가 커지고 기능이 복잡해지면 이 코드는 부채가 됩니다. 저는 실무에서 WYSIWYG 에디터 컴포넌트를 개발할 때 이 문제를 뼈저리게 느꼈습니다.
에디터는 사용자가 입력한 HTML을 그대로 보여줘야 하는데, 전역 스타일이 침범하면서 문제가 터집니다.
- 전역
p { margin-bottom: 1rem; }가 에디터 내부의 문단 간격을 망침 .container table스타일이 에디터 안의 표까지 덮어씀- 이를 막기 위해
.editor-content p { margin-bottom: 0 !important; }추가 - 나중에 에디터 내부에서도 특정 간격이 필요해지며 더 강력한 선택자 필요
결국 아래와 같은 괴물 선택자가 탄생합니다.
/* 우선순위 전쟁의 결과물 */
.editor-content .post-body p:not(.no-margin) {
margin-bottom: 1.5em !important;
}이런 우선순위 싸움은 한 번 시작되면 끝이 없습니다. 단순한 스타일 수정 하나에 수십 분을 디버깅하게 되고, 어느 순간 CSS 파일은 아무도 건드리기 싫은 지뢰밭이 됩니다. 팀원 누구도 사이드 이펙트를 예측할 수 없기 때문입니다.
이런 문제는 에디터 컴포넌트만의 이야기가 아닙니다.
- 외부 라이브러리 충돌: Datepicker나 결제 위젯을 도입했는데, 전역
input스타일 때문에 UI가 깨져서 라이브러리 내부 클래스를 억지로 덮어쓰는 경우 - 독립적인 랜딩 페이지: 메인 앱과 디자인이 다른 마케팅 페이지를 만들어야 하는데, 이미 전역에 선언된
body,h1스타일을 리셋하는 데에만 한 세월을 보내는 경우 - 클래스명 충돌: 서로 다른 페이지에서 우연히 사용한
.card,.item클래스가 겹쳐서, 엉뚱한 곳의 레이아웃이 무너지는 경우
이 모든 것이 CSS가 전역으로 동작하기 때문에 발생하는 비용입니다. 스타일을 만드는 시간보다, 스타일이 충돌하지 않게 방어하고 격리하는 데 더 많은 시간을 쓰게 됩니다.
핵심은 '격리(Isolation)'입니다
개발 인원이 늘어나고 프로젝트 규모가 커질수록 가장 중요한 건 예쁜 코드가 아니라 격리된 코드라고 생각합니다.
저는 다수의 프론트엔드 개발자와 함께 규모 있는 프로젝트들을 진행해왔습니다. 팀 규모가 커지면 역할이 분담되는데, 이 상황에서 누군가 global.css를 수정하면 검토해야 할 범위가 서비스 전체로 늘어납니다. 이건 명확한 비용입니다.
물론 CSS 파일을 잘게 쪼개거나 네이밍 규칙으로 해결할 수 있다고들 합니다. 하지만 현실적으로 수많은 개발자가 투입되는 환경에서, 파일 분리만으로 완벽한 격리가 유지되는 경우를 저는 거의 보지 못했습니다. 사람의 주의력에 의존하는 격리는 결국 한계가 있기 마련입니다.
반면, Tailwind CSS의 className 방식은 스타일 정보를 해당 HTML 요소 안에 완벽하게 가둡니다. 제가 이 버튼의 색상을 바꿔도, 다른 페이지의 버튼이 깨질 걱정을 할 필요가 없습니다. 부작용이 제로입니다.
물론 중복 코드가 발생합니다. 하지만 요즘 IDE 성능이 좋고 검색 기능도 뛰어나기 때문에 중복 자체가 크게 문제가 되지 않습니다. 그리고 현대 프론트엔드 개발에서 중복을 해결하는 올바른 방법은 CSS 클래스를 묶는 것이 아니라, 컴포넌트로 추상화하는 것입니다.
// 나쁜 예: CSS로 공통화 (의존성 발생)
<button className="btn-primary">...</button>
// 좋은 예: 컴포넌트로 격리 (로직과 스타일을 캡슐화)
<Button variant="primary">...</Button>공통 로직과 스타일은 컴포넌트 단위로 나누고, 그 내부 구현은 Tailwind CSS의 유틸리티 클래스로 채우는 것. 이것이 부작용을 최소화하고 확장성을 확보하는 가장 현실적인 방법이라고 생각합니다.
CSS-in-JS와의 차이
CSS-in-JS 같은 라이브러리들도 격리 문제를 훌륭하게 해결해 줍니다. 하지만 저는 지속 가능성 측면에서 Tailwind CSS가 더 유리하다고 생각합니다.
CSS-in-JS는 자바스크립트 런타임과 특정 라이브러리의 문법에 강하게 의존합니다. 만약 라이브러리가 업데이트를 멈추거나, React의 버전이 올라가면서 호환성 문제가 생기면 대응하기가 매우 까다롭습니다.
협업 관점에서도 새로운 문법을 배우는 건 비용입니다. CSS-in-JS는 라이브러리마다 문법이 다르고, 팀에 새로운 사람이 합류할 때마다 학습이 필요합니다. 반면 Tailwind CSS는 순수 class 속성만 사용하기 때문에 CSS를 아는 사람이라면 누구나 빠르게 적응할 수 있습니다.
그리고 Tailwind CSS는 결국 문자열입니다. 복잡한 로직이 숨어있지 않고, 빌드되고 나면 순수한 CSS 파일만 남습니다. 먼 훗날 Tailwind CSS가 사라지거나 트렌드가 바뀐다 해도, 우리가 작성한 코드는 단순히 클래스명을 나열한 문자열일 뿐입니다. 특정 런타임 로직에 묶여 있는 코드보다 훨씬 쉽게 마이그레이션하거나 유지할 수 있습니다.
AI 시대, Tailwind CSS는 선택이 아닌 표준
ChatGPT, Claude, Cursor 등 코딩을 도와주는 거의 모든 AI 도구는 스타일링 요청 시 Tailwind CSS를 기본으로 사용합니다.
단순히 인기가 많아서는 아니라고 생각합니다. 저는 그 이유가 문맥 비용 때문이라고 봅니다. AI 입장에서 별도로 정의된 CSS 파일을 오가며 문맥을 파악하고 코드를 짜는 것은 비용이 많이 드는 작업입니다.
이건 AI뿐만 아니라 사람에게도 똑같이 적용됩니다. 관련 있는 코드(구조와 스타일)가 한 위치에 모여 있는 것(Locality of Behavior)은 유지보수와 협업에 이점이 있습니다. 수정할 범위가 해당 위치로 줄어드는 만큼, 부작용 예측이나 QA도 훨씬 수월해집니다.
AI와 함께 일하는 것이 당연해진 시대에, AI가 잘 다루는 도구를 사용하는 것은 생산성에 직결됩니다.
마무리
Tailwind CSS는 단순히 스타일을 입히는 도구가 아닙니다. CSS의 전역 오염 문제를 해결하기 위한 아키텍처입니다.
클래스 이름이 길어지는 건 사실입니다. 하지만 그 덕분에 불확실성이 사라지고, 격리된 안전함을 얻을 수 있습니다. 혼자 만드는 토이 프로젝트가 아니라면, 팀과 AI가 함께 일하는 환경이라면 CSS 파일을 생성하고 수정하기 전에 Tailwind CSS를 고려해보는 걸 권합니다.