내가 tailwindcss를 사용하는 이유
심진석
수정일
styled-components, emotion 같은 css-in-js가 유행하던 때에 뜬금없이 tailwindcss가 등장한다.
물론 과거에도 tailwindcss와 같은 접근은 있었고, 가장 인기있었던 bootstrap에서도 유용하게 사용했지만 인기가 식어가는 라이브러리였다. 그런데 어떻게 이러한 접근이 다시 인기가 생겼을까?
기존의 CSS
알다시피 CSS를 사용하여 박스box를 꾸밀 수 있다. 보통 셀렉터로 클래스를 활용해 박스를 꾸민다.
<style>
.button {
border: 1px solid black;
}
</style>
<button class="button">버튼!</button>
위 예시는 간단하지만 실무에서는 아래와 같이 사용하기도 한다.
.main { /* ... */}
.main .card { /* ... */}
.main .card .head { /* ... */}
.main .card .head .title { /* ... */}
.main .card .body { /* ... */}
/* 아래가 실제로 사용되는 예제 */
div.footer div.inner > div.flex > div.flex-sns > ul > li > a {color: #fff; font-size: 30px;}
스타일 관리 기법은 몇가지 있지만 국내에서는 위와 같은 방법이 유행했던 것 같다.
그러던 중 트위터에서 bootstrap이라는 라이브러리를 만들었는데, 지금으로 치면 컴포넌트라는 개념을 만들었다고 볼 수 있겠다. foundation, bulma도 후발주자로 인기를 얻었다.
그런데 SPA가 유행하면서 React가 대세가 되면서 문제가 발생했다.
- HTML문서가 하나가 아니라 여러개의 컴포넌트로 나뉘면서 어떤 스타일파일을 수정해야할지 찾기 어려워졌다.
- 상태에 맞게 엘리먼트의 스타일을 바꾸는게 까다롭다.
여기서 styled-components
혜성처럼 등장하고 emotion
도 유행하면서 css-in-js
가 대세가 된 상태였다. 그러던 중 tailwindcss
가 등장한 것이다.
tailwindcss란 무엇인가?
공식 문서에서는 Utility-First CSS Framework라고 표현하고 있다. buttons, cards 같은 조합된 구성이 아니라 flex, absolute 같이 최소 단위의 스타일을 클래스로 만든 것이다.
<div class="flex justify-between">
<button>취소</button>
<button class="bg-primary">확인</button>
</div>
스타일 시트를 보면 다음과 같다.
.flex { display: flex; }
.justify-between { justify-content: space-between; }
.bg-primary { background-color: rgb(87 83 78); }
사용시 장점
편리해지는 소스관리
이렇게 최소 단위를 사용하면 마크업이 엄청 편해진다. 아까 위에서 봤던 스타일시트 작성을 따르려면 마크업을 바꾸었을 때 셀렉터 또한 바꾸어야한다는 단점이 존재한다.
<!-- 기존 -->
<div class="card">
<div class="card-header">
<p class="card-header__title">제목</p>
<button class="cart-header__button">변경</button>
</div>
</div>
<!-- 변경 후 -->
<div class="card">
<div class="card-title">제목</div>
<div class="card-footer">
<button class="card-footer__button">변경</button>
</div>
</div>
수천, 수만 라인의 소스코드를 다루는 실무에서는 이런 변경이 생길 때 해당하는 스타일 코드는 어디에 있는지, 변경하면 다른 페이지에는 영향이 없는지 스트레스가 쌓이기 시작한다.
이름 짓는 스트레스에서 해방
이름을 매번 짓는 것도 엄청난 스트레스이고, 이름을 짓기 애매하지만 레이아웃을 위해 블록박스를 만들어야 하는 상황이 생긴다.
<div class="article">
<div class="hero">...</div>
<!-- 이건 이름 뭐라고 지어야하지 -->
<div class="">
...
</div>
</div>
tailwindcss를 사용하면 이름 짓느라, 마크업 구조 생각하며 셀렉터 생각해내느라 고민하는 시간이 확 줄어들게 된다.
<div class="container">
<div class="relative ...">...</div>
<div class="flex items-end justify-betwenn">
...
</div>
</div>
그럼 인라인 스타일을 사용하면 되지 않나?
바로 이런 생각이 들었다. 스타일 문법과 동일하니 인라인 스타일을 적용하면 되지 않나?
<div style="display: flex; justify-content: space-between;">
html
</div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
jsx
</div>
tailwindcss를 쓰면서도 간혹 인라인 스타일을 사용할 때가 있지만, 사실 그렇게 추천하고 싶진 않다.
단점도 당연히 있다
1. 클래스가 굉장히 길어진다.
<div class="relative left-1/2 -z-10 aspect-[1155/678] w-[36.125rem] max-w-none -translate-x-1/2 rotate-[30deg] bg-gradient-to-tr from-[#ff80b5] to-[#9089fc] opacity-30 sm:left-[calc(50%-40rem)] sm:w-[72.1875rem]">
...
</div>
물론 스타일시트로 작성하면 코드량이 훨씬 많겠지만, 한 줄에 저렇게긴건 나도 당황스럽고 최소화하려고 노력한다.
특히 리액트의 경우엔 상태에 따라 클래스 수정이 필요한데, 그 때 classnames
나 clsx
같은 라이브러리를 사용하면 편하다.
<div className={clsx('font-bold', isActive ? 'bg-primary' : 'bg-white', isLoading && 'text-white')}>
...
</div>
2. 용량이 비대해진다.
초기엔 CSS 파일 하나가 2MB, 4MB였다가 기능이 늘어나면서 8MB, 13MB 까지 늘었다. 그도 그럴게 갖가지 경우의 수를 때려박았는데, 용량이 작을 수 없다.
당시엔 대 jQuery 무법시대도 막을 내리고 최적화에도 신경쓰고 있던 터라 특히 CSS가 메가바이트라는 사실은 용납할 수 없었다. 그래서 초기엔 프로덕션에 적용한 사람은 많이 없었을 것이다.
하지만 purgecss가 기본으로 장착된 덕분에 용량 문제는 해결되었다.
잘 정의된 컴포넌트를 사용하면 안되나?
모든 개발자는 잘 정리된 소스코드를 원할 것이다.
한번은 온 에너지를 쏟아 컴포넌트 단위로 이름과 수식어를 정리한 적 있었다. 이제 재사용만 하면 되겠지 했다.
수 개월이 지나자 새로운 디자인 컨셉이 나왔고, 잘 정리된 컴포넌트는 버튼 하나 제거하려해도 시간이 너무 오래 걸려 사실상 옛날 페이지에서만 사용되었다.
하지만 tailwindcss를 사용하면서 마크업이 변해도 큰 스트레스가 없다.
앞으로 몇년간 대세를 이어갈 듯
최근 이직을 하고나서 내 개발속도가 빠르다는 칭찬을 듣고 놀란 적 있다. 그 땐 왜지?라고 의문만 가졌다가, 이 글을 작성하면서 tailwindcss를 사용한 덕이라는 것을 체감하게 되었다.
CSS의 업데이트로 편의 기능이 많이 생긴 것이 큰 요인이겠지만, 장인정신을 가지고 마크업, 네이밍 하나하나에 신경쓰면 버튼 하나 배치하는데도 수십분이 걸릴 수 있겠다는 생각이 들었다.
css 문법을 파괴한다느니 클래스가 길어진다느니 등으로 선호하지 않는 사람들이 있다. 이해한다.
새로운 값을 정의하고, 거의 모든 스타일을 적용할 수 있는데다 미디어 뿐만 아니라 자식 요소도 제어할 수 있는 클래스가 등장하면서 tailwindcss는 더 강력해졌다. 앞으로 더 많은 사람들이 사용할 것이라 생각된다.