https://doohyeong.tistory.com/211
css 뭐써볼까에서 시작됐고 tailwindcss를 사용하기로 해봤다. 이미 side project에서 사용해봤지만 우선 편하게 사용하기 급급해서 공식문서를 지금까지도 읽어보진 않았다. 필요한게 생기면 추가하고, 현재는 개선할 때 더 추가하거나 리팩토링 해야한다. RSC의 장점을 살리고 빠르게 poc를 검증하기 위한 단계라고 생각한다.
그 와중에 나온 내용은 reusing style이다. 우리팀도 아니고 같은 프로젝트를 진행하지 않지만 구경오신 @재성 "https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply" 적용하면 더 깔끔할거 같아요.
아래는 기존의 내 코드 상태였고, primary color를 theme에 extend하여 사용한게 전부였다. 나머지는 tailwindcss가 이름을 생각하지 않고 만드는 css라고 생각했기에 불필요하다고 느껴졌었다.
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
"./components/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
primary: "#0191e0",
},
},
},
plugins: [],
};
그 와중에 리뷰를 주신분은 나 또한 공감 가능한 가능한 반복되는 부분을 짚어주셨다. 바로 h1, h2, ..., h6 태그였다. 모든 코드가 공통되는 부분을 일정하게 사용하지 않고 있었다. 때문에 페이지마다 계속해서 복사 붙혀넣기를 하고 그럼에도 불구하고 일정하게 유지되지 않을 수 있겠다는 생각을 해서 감사함을 표하고 즉각 문서를 읽고 개선된 코드를 다시 리뷰 요청드렸고 따봉👍을 주셨다.
// global.css
@tailwind base;
@tailwind components;
@tailwind utilities;
// 새롭게 추가된 부분
@layer components {
h1 {
@apply font-bold text-black text-lg ...
}
h2 {
@apply ...
}
...
}
얼마 뒤 똑같은 문제로 이번엔 @성준님이 리뷰를 남겨주셨다. "반복되는 클래스의 경우 재사용할수있게 아래와같이 apply를 적용해볼수있을거같습니다. 참조: https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply"
.profile-item { @apply flex justify-center items-center px-1 py-3; }
바쁘신 와중에 다른 프로젝트를 구경하러 오셔서 리뷰를 남겨주셨는데 똑같은 링크였다. 👍22bro and g2g2 reacted with thumbs up emoji. 우선 관심에 따봉을 드리고 고민후 답변을 드렸다.
나: "보내주신 링크를 봤는데 현재의 경우에, Reusing Styles 탭에서 소개한것 처럼
두 가지로 해결하는게 현재의 경우에는 좋아보입니다.
Avoiding premature abstraction
Whatever you do, don’t use @apply just to make things look “cleaner”. Yes, HTML templates littered with Tailwind classes are kind of ugly. Making changes in a project that has tons of custom CSS is worse.
If you start using @apply for everything, you are basically just writing CSS again and throwing away all of the workflow and maintainability advantages Tailwind gives you, for example:
You have to think up class names all the time — nothing will slow you down or drain your energy like coming up with a class name for something that doesn’t deserve to be named.
You have to jump between multiple files to make changes — which is a way bigger workflow killer than you’d think before co-locating everything together.
Changing styles is scarier — CSS is global, are you sure you can change the min-width value in that class without breaking something in another part of the site?
Your CSS bundle will be bigger — oof."
👍1sungjoonlee reacted with thumbs up emoji👀1g2g2 reacted with eyes emoji
멀티커서는 재사용성보단 팁인거같고 과도한 추상화를 피하는걸 권장하는거같네요
tailwind 권장방식은 현재 케이스에선 따로 @apply를 적용하는거보단 기존 그대로 반영하는게 맞겠네요
tailwindcss 사용해보지 않았음에도 문서를 공유해주시고 관심과 의견을 자유롭게 공유하고 쿨하게 따봉날리고 가주셔서 덕분에 공식 문서의 일부분을 한 번 읽어보게 된 계기가 됐다. 팀원분은 전체를 읽지 않고 일부분을 읽었고 리뷰에 답변하기 위해 전체를 읽어 서로 부족한 부분을 보완해주는 나와 잘맞는 좋은 팀원과 일함에 감사한다.
Utility-First Fundamentals 라는 좋은 경험
처음 아래 코드블럭을 본다면 굉장히 지저분하게 느껴져서 <style> 태그 안에 class를 지정하고 싶을겁니다. 초기 러닝커브가 있지만 사실 우리는 대충 어떤 뜻인지 이해할 수 있고 vscode extension과 같은 플러그인에서 뜻을 제공하고 자동완성을 제공하기에 생각보다 금방 익힐 수 있습니다.
왜 이렇게 쓰는게 장점인가하면,
- 클래스 이름을 만드는데 에너지를 낭비하지 않습니다.
- CSS 파일이 커지지 않습니다.
- 전역 CSS로부터 안전합니다.
- 인라인 스타일을 작업하는듯한 개발 경험을 제공해줍니다.
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
<div class="shrink-0">
<img class="h-12 w-12" src="/img/logo.svg" alt="ChitChat Logo">
</div>
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-slate-500">You have a new message!</p>
</div>
</div>
아래는 추가로 좋은 'tailwindcss에서 혼란을 방지하기 위한 5가지 방법' 에 관한 Velog 글이 있어서 (해외글 번역입니다) 요약과 링크를 첨부하겠습니다.
정확하고 현명하게 tailwindcss를 사용하기 위해서 첫 번째로 프로젝트에 디자인 시스템이 있어야 합니다.
.button {
background-color: oklch(45% 0.2 270);
}
.tab {
background-color: oklch(45% 0.2 270);
}
디자이너와 개발자가 일관된 디자인 토큰을 사용하는 디자인 시스템과 함께합니다. 디자인 토큰은 이러한 문제를 방지하고 UI 요소 전반의 일관성을 보장하는 데 도움이 됩니다. tailwind.config.js에 토큰을 정의하기만 하면 됩니다. 'p-[123px] mb-[11px] gap-[3px]'와 같이 일관되지 않은 디자인은 피하는게 좋습니다.
// tailwind.css
module.exports = {
theme: {
colors: {
primary: 'oklch(45% 0.2 270)'
}
}
}
// html
<button class="bg-primary">Standard button</button>
<div class="bg-primary">First tab</div>
둘째로 이미 컴포넌트 기반 접근 방식을 사용하고 있어야 한다는 것입니다.
<!-- 재사용 가능한 버튼으로 긴 Tailwind CSS 클래스 목록을 가지고 있습니다. -->
<button class="bg-yellow-700 border-2 font-semibold border border-gray-300 text-green p-4 rounded">
Custom Button
</button>
<!-- 이 구조를 계속 반복하는 대신 재사용 가능한 컴포넌트를 만드세요. -->
<CustomButton>Custom Button</CustomButton>
마지막으로 컴포넌트 기반 접근 방식과 관련하여 한 가지 더 강조해보면 @apply 지시문을 피하는 것이 좋습니다.
.block {
@apply bg-red-500 text-white p-4 rounded-lg active:bg-blue-700 active:text-yellow-300 hover:bg-blue-500 hover:text-yellow-300;
}
이는 @apply를 사용하면 컴포넌트 내에서 격리되지 않기 때문입니다. 또한 CSS 번들 크기가 증가합니다.
1. 가능한 한 적은 수의 유틸리티 클래스 사용
pt-4 pb-4 -> py-4
flex flex-row justify-between -> flex justify-between
border border-dotted border-2 border-black border-opacity-50 -> border-dotted border-2 border-black/50
2. 디자인 토큰을 그룹화하고 의미적으로 이름 짓기
module.exports = {
theme: {
colors: {
primary: 'oklch(75% 0.18 154)',
secondary: 'oklch(40% 0.23 283)',
error: 'oklch(54% 0.22 29)'
},
spacing: {
'sm': '4px',
'md': '8px',
'lg': '12px'
},
screens: {
'sm': '640px',
'md': '768px'
},
},
//...
3. 클래스 순서 유지 - Tailwind CSS용 공식 Prettier 플러그인
4. 빌드 크기 최소화
Tailwind 버전 3.0 이상을 사용하는 경우 프로젝트에서 JIT(Just-in-Time) 엔진이 기본적으로 활성화되어 있어 CSS 스타일이 생성되므로 프로덕션 빌드에서 사용하지 않는 스타일을 제거할 필요가 없습니다. 하지만 이전 버전의 Tailwind를 사용하는 경우 빌드에 대한 추가 최적화를 수행해야 하는데, 사용하지 않는 CSS를 제거하는 도구인 PurgeCSS를 사용하여 이 작업을 수행할 수 있습니다.
module.exports = {
mode: 'jit',
...
}
이렇게 하면 번들에 필요한 스타일만 포함할 수 있습니다. npx tailwindcss -o build.css --minify
스타일이 있는 컴포넌트의 개수가 적은 작은 프로젝트에서도 CSS를 축소하고 JIT 모드를 활성화하면 30% 이상의 크기 차이가 있습니다. 이러한 효과를 보기 위해서는 위에서 설명한 대로 minify 플래그를 추가하고 jit 모드를 활성화하기만 하면 됩니다.
5. 스타일 덮어쓰기 및 확장 시 불일치 방지
// 현재 버튼
<Button className="bg-black" />
// 기본 스타일이 있는 버튼
export const Button = () => {
return <button className="bg-white">Test button</button>
}
// 확장하고 싶은 기본 스타일이 있는 버튼
export const Button = ({ className = "bg-white" }) => {
return <button className={className}>Test button</button>
}
프롭을 통해 임의의 유틸리티 클래스를 전달할 수 있도록 허용하는 대신 미리 정의된 변형 집합을 정의합니다. 그런 다음 Button 컴포넌트를 변경하여 variant 프롭을 사용할 수 있도록 합니다. className을 더 편리하게 구성하려면 clsx를 사용할 수 있습니다.
export const Button = ({ className, variant = BUTTON_VARIANTS.primary }) => {
return <button className={clsx(className, variant)}>Test Button</button>
}
<Button variant="secondary" />
원문:
https://evilmartians.com/chronicles/5-best-practices-for-preventing-chaos-in-tailwind-css
https://velog.io/@lky5697/5-best-practices-for-preventing-chaos-in-tailwind-css
'software engineering > frontend' 카테고리의 다른 글
next.js 13.4 / 13.5.6 / 14.0.2 로컬 구동 시간 비교 (0) | 2023.11.14 |
---|---|
UX 패턴 분석 - 로딩(번역) (1) | 2023.11.12 |
예측하지 못한 useCallback, react.memo 상황 (1) | 2023.10.29 |
Type validation 뭐 써볼까? (0) | 2023.09.21 |
Monorepo 뭐 써볼까? (0) | 2023.09.21 |