이번에 새롭게 블로그를 만들면서 Tailwind CSS를 사용해봤습니다. Tailwind CSS는 익히 들어서 알고 있었지만 몇 가지 거부감에 그동안 사용하길 꺼렸습니다. 언뜻보기에 인라인 스타일과 다를 바 없어보이는 클래스들을 나열한다는게 어색했습니다. 게다가 기존의 CSS in CSS나 CSS in JS와 달리 이름없이 만들어진 컴포넌트들을 다른 사람이 이해할 수 있을지가 의문이었습니다.
그럼에도 사용하게된 이유
뒤늦게서야 제 스스로가 Utility-First에 대한 의문을 가지면서 동시에 프로젝트에 적용하고 있었다는걸 깨달았습니다.
tsx
import styled from 'styled-components';
export const Flex = styled.div`
display: flex;
`;
export const FlexCenter = styled(Flex)`
justify-content: center;
align-items: center;
`;
...
export const Ellipsis = styled.div`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
tsx
import styled from 'styled-components';
export const Flex = styled.div`
display: flex;
`;
export const FlexCenter = styled(Flex)`
justify-content: center;
align-items: center;
`;
...
export const Ellipsis = styled.div`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
이런 식으로 레이아웃을 지정하기도 하고,
tsx
const devices = {
mobile: '(max-width: 576px)',
tablet: '(max-width: 992px)',
desktop: '(max-width: 1200px)',
};
const theme = { devices };
export default theme;
tsx
const devices = {
mobile: '(max-width: 576px)',
tablet: '(max-width: 992px)',
desktop: '(max-width: 1200px)',
};
const theme = { devices };
export default theme;
이렇게 테마도 지정해서 사용했었습니다. Sass(SCSS)와 같은 CSS-in-CSS를 사용할 때도 마찬가지였습니다.
위와 같이 작성했던 유틸리티들이 편하다고 생각했던 이유는 무엇일까요?
작은 단위로 이루어져서 다른 컴포넌트에서 손쉽게 사용할 수 있다.
직관적인 네이밍으로 적용 후에 어떤 일이 일어나는 지 바로 알 수 있다.
이처럼 유틸리티들의 장점을 저도 모르게 느끼고 있었습니다. 동시에 Tailwind CSS에서 추구하는 Utility-First 컨셉에 공감하게 되면서 사용을 결정했습니다.
사용하면서 해소된 몇 가지 오해
CSS의 의미론적 요소는 어디에?
CSS 시맨틱
CSS의 경우입니다. 다양한 종류의 과일을 나타내기 위해서는 리스트 태그 li 가 있다고 가정해봅시다. div> ul> li 와 .fruits__item 둘 중 어떤 것이 어떤 DOM부분이 선택되었는지 잘 알려줄까요?
인라인 스타일은 적용한 엘리먼트에만 영향을 줍니다. 바꿔 말하면 적용한 엘리먼트 외 요소들과 상호작용 할 수 없습니다. 예를 들어 :hover와 같은 의사 클래스나 미디어 쿼리 등은 사용할 수 없게 됩니다.
반면에 Tailwind CSS는 PostCSS와 같은 전처리기를 거쳐서 스타일 시트를 생성하게 됩니다. 덕분에 인라인 스타일에서 할 수 없었던 것들을 할 수 있게 됩니다.
index.html
html
<li class="hover:text-orange">Orange</li>
index.html
html
<li class="hover:text-orange">Orange</li>
위와 같이 호버 시에 글자 색이 바뀌는 행동을 유틸리티 클래스를 통해 할 수 있습니다.
소소한 팁
블로그에서 Tailwind CSS를 사용하면서 유용했던 몇 가지를 정리해보려고 합니다.
IntelliSense
공식 Tailwind CSS IntelliSense를 사용하면 Visual Studio Code에서 자동 완성, 문법 강조, 린팅 등의 기능을 이용할 수 있습니다. 제가 tailwind.config.ts에 정의해놨던 스타일들도 똑같이 지원해줘서 좋았습니다.
Prettier Plugin
공식 Prettier Plugin을 통해서 권장된 클래스 순서대로 자동 정렬을 지원합니다. 스타일링에 필요한 클래스를 쭉 나열해서 사용하면서 나중에 수정하게 됐을 때 동일한 순서로 정리해줘서 정말 편리했습니다. 덤으로 중복된 클래스를 적는 일도 사라졌습니다.
shell
yarn add -D prettier-plugin-tailwindcss
shell
yarn add -D prettier-plugin-tailwindcss
.prettierrc.json
json
{
...,
"plugins": ["prettier-plugin-tailwindcss"]
}
.prettierrc.json
json
{
...,
"plugins": ["prettier-plugin-tailwindcss"]
}
Custom Styles
Tailwind CSS에서 충분히 많은 기본적인 스타일을 지원하지만 필요에 따라서 커스텀 스타일을 추가해야되는 경우가 있습니다. 저는 이 블로그를 개발하면서 다양한 색을 사용했는데 arbitrary values 없이 개발하고자 했기 때문에 모든 색을 등록해서 사용했습니다.
tailwind.config.ts
ts
import type { Config } from 'tailwindcss';
export default {
theme: {
...,
extend: {
colors: {
light: {
DEFAULT: '#dddddd',
mute: '#595959',
link: '#004ec7',
background: '#eef1f5',
line: '#e5e7eb',
code: {
DEFAULT: '#ea580c',
background: '#fb923c1a',
},
},
dark: {
DEFAULT: '#191c1f',
mute: '#b3b3b3',
link: '#10b981',
background: '#222527',
line: '#3a3e42',
code: {
DEFAULT: '#a78bfa',
background: '#f3e8ff1a',
},
},
dimmed: '#00000066',
},
},
},
} satisfies Config;
tailwind.config.ts
ts
import type { Config } from 'tailwindcss';
export default {
theme: {
...,
extend: {
colors: {
light: {
DEFAULT: '#dddddd',
mute: '#595959',
link: '#004ec7',
background: '#eef1f5',
line: '#e5e7eb',
code: {
DEFAULT: '#ea580c',
background: '#fb923c1a',
},
},
dark: {
DEFAULT: '#191c1f',
mute: '#b3b3b3',
link: '#10b981',
background: '#222527',
line: '#3a3e42',
code: {
DEFAULT: '#a78bfa',
background: '#f3e8ff1a',
},
},
dimmed: '#00000066',
},
},
},
} satisfies Config;
위와 같이 nested object로 작성하면 -로 이어서 코드에서 사용할 수 있습니다.
html
<div class="text-light-mute"></div>
html
<div class="text-light-mute"></div>
DEFAULT로 작성된 부분은 입력하지 않고도 사용할 수 있습니다.
html
// light: { DEAFULT: '#dddddd' }
<div class="text-light"></div>
html
// light: { DEAFULT: '#dddddd' }
<div class="text-light"></div>
이 뿐만 아니라 애니메이션도 등록해서 사용할 수 있습니다. 블로그 메인 페이지에서 글 리스트에 마우스를 호버하면 이모지가 회전하는 걸 구현하기 위해서 사용했습니다.
직접 사용해본 결과 전적으로 공감가는 말이었습니다. 초반에는 스타일을 지정해줄 때 하나하나 공식 문서에 검색했는데 적응한 이후로는 훨씬 빠르게 개발이 가능했습니다. 문법에 어느정도 일관성이 있기 때문에 나중에는 기억나지 않더라도 유추해서 작성하는 것도 가능했습니다.
styled-component를 사용하면서 이름 짓는데 많은 시간을 사용하면서 고통 받았는데 해방되는 기분도 들었습니다. 네이밍 컨벤션을 결정하거나, 이런 작은 컴포넌트까지 이름을 지어줘야하는지 고민하는데 드는 시간을 많이 줄인 것 같습니다.
또한 정의된 스타일을 통해 개발하기 때문에 일관된 스타일을 유지할 수 있었습니다. 게다가 스타일링을 위해서 파일이나 커서를 옮겨야하는데 드는 컨텍스트 스위칭 시간도 없어서 편리했습니다.
앞서 Tailwind CSS의 좋은 점만 나열하게 된 것 같은데 꼭 그런 것은 아닙니다. 동적 스타일링을 하기 힘들기 때문에 외부 플러그인에 도움을 받아야하는 경우가 생깁니다. 아쉽게도 블로그를 개발하면서는 동적 스타일링을 할 경우가 많지 않았습니다. 하지만 나중에 규모가 큰 프로젝트에서 사용하게 될 때는 지나칠 수 없는 문제가 될 것 같습니다.
그리고 개인 프로젝트 외에 현업에서 사용해본 적은 없지만 디자인 시스템이 없거나 있어도 애매한 부분에는 arbitrary values가 점점 쌓이면서 금새 복잡해질 것 같다는 생각이 듭니다.
끝으로 많은 선입견을 갖고 있던 Tailwind CSS를 직접 사용해보면서, 기존에 개발하면서 가지고 있던 불편함들이 다양한 방법으로 해소되는 경험을 할 수 있었습니다. 세상에 완벽한 도구란 없는 것 같고, 필요한 도구를 적합한 장소에 사용할 줄 아는 개발자가 되어야겠습니다.