๐ŸŽจ Tailwind 1์žฅ: ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค ๋ฉ˜ํƒˆ ๋ชจ๋ธ

2026๋…„ 3์›” 5์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

CSS๋ฅผ ํด๋ž˜์Šค ๋‹จ์œ„๋กœ ์ชผ๊ฐœ๋Š” utility-first ์ฒ ํ•™ โ€” ์™œ Tailwind๋Š” ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ฒ˜๋Ÿผ ๋ณด์ด๋Š”๋ฐ๋„ ์‹œ๋‹ˆ์–ด๋“ค์ด ์—ด๊ด‘ํ•˜๋Š”๊ฐ€?

๐Ÿ“‹ ๋ชฉ์ฐจ


๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 15๋ถ„ (์ „์ฒด) / ํ•ต์‹ฌ ํŒŒํŠธ๋งŒ: 8๋ถ„

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
์ „ํ†ต CSS ์˜ ๊ณ ํ†ต โ†’ utility-first ์˜ ํƒ„์ƒ ๋ฐฐ๊ฒฝ โ†’ Tailwind ํด๋ž˜์Šค ํ•ด๋ถ€ โ†’ Before/After ์‹ค์ „ ๋น„๊ต

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • "Tailwind๋Š” ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ด๋ž‘ ๋ญ๊ฐ€ ๋‹ฌ๋ผ์š”?"๋ผ๋Š” ์งˆ๋ฌธ์— ์‹œ๋‹ˆ์–ด์ฒ˜๋Ÿผ ๋‹ต๋ณ€ํ•  ์ˆ˜ ์žˆ๋‹ค
  • className="flex items-center gap-4 rounded-xl bg-white p-6 shadow-lg" ๊ฐ™์€ ํด๋ž˜์Šค ๋‚˜์—ด์ด ์™œ ์˜ฌ๋ฐ”๋ฅธ ์„ค๊ณ„์ธ์ง€ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค
  • BEM, CSS Modules, Tailwind ์ค‘ ์ƒํ™ฉ์— ๋”ฐ๋ผ ๋ฌด์—‡์„ ์จ์•ผ ํ• ์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  (์‹ ์ž…): "๋ฆฌ๋“œ ๋‹˜! ์ € Tailwind ์จ๋ดค๋Š”๋ฐ์š”, ํด๋ž˜์Šค๊ฐ€ HTML ์— ๋„ˆ๋ฌด ๋งŽ์ด ๋ฐ•ํžˆ๋Š” ๊ฒƒ ๊ฐ™์•„์„œ... ์ œ ์ด์ „ ํŒ€์žฅ ๋‹˜์€ ์ด๊ฒŒ ์œ ์ง€๋ณด์ˆ˜ ์ง€์˜ฅ์ด๋ผ๊ณ  ํ•˜์…จ๊ฑฐ๋“ ์š”?"
  • ๐Ÿฆ ์˜ํ˜ธ (๋ฆฌ๋“œ): "์˜์ฒ  ๋‹˜, ๊ทธ ํŒ€์žฅ ๋ถ„์ด 2018๋…„ Tailwind ๋ฅผ ๋ณด์‹  ๊ฑฐ ์•„๋‹๊นŒ์š”? ์ง€๊ธˆ์€ ๋‹ฌ๋ผ์š”. class="flex items-center p-6" ์ด 10๊ฐœ BEM ํด๋ž˜์Šค๋ฅผ 5๊ฐœ CSS ํŒŒ์ผ์— ๋‚˜๋ˆ  ์“ฐ๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ์ถ”์ ์ด ์‰ฝ๊ฑฐ๋“ ์š”."
  • ๐Ÿ‘” ์˜์ˆ˜ (PM): "์ €๋Š” ์–ด๋–ค ๋ฐฉ์‹์ด๋“  ๋น ๋ฅด๊ฒŒ ๋‚˜์˜ค๋ฉด ๋ฉ๋‹ˆ๋‹ค๋งŒ... ์ตœ๊ทผ์— ๋””์ž์ธ ์ˆ˜์ • ์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ๋งˆ๋‹ค CSS ํŒŒ์ผ ์ฐพ๋А๋ผ ๋‹ค๋“ค ํž˜๋“ค์–ดํ•˜๋Š” ๊ฒƒ ๊ฐ™๋”๋ผ๊ณ ์š”."
  • ๐ŸŽจ ์˜์ˆ™ (๋””์ž์ด๋„ˆ): "์ €๋„ ๊ณต์œ ๋ฐ›์€ HTML ์—์„œ ์–ด๋–ค ์Šคํƒ€์ผ์ด ์–ด๋””์„œ ์˜ค๋Š”์ง€ ํŒŒ์•…์ด ๋„ˆ๋ฌด ์–ด๋ ค์› ์–ด์š”. ํด๋ž˜์Šค ์ด๋ฆ„์ด card__title--active ๊ฐ™์€ ๊ฑด๋ฐ CSS ํŒŒ์ผ์„ 10๊ฐœ๋‚˜ ๋’ค์ ธ์•ผ ํ•˜๋”๋ผ๊ณ ์š”."

๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€

์˜์ฒ ์ด๋Š” ์ง€๊ธˆ๊ป CSS ๋ฅผ ์ด๋ ‡๊ฒŒ ์จ์™”์–ด:

/* styles/card.css */
.card { border-radius: 12px; background: white; padding: 24px; box-shadow: 0 4px 6px rgba(0,0,0,.1); }
.card__title { font-size: 20px; font-weight: 700; color: #111; }
.card__badge { background: #dbeafe; color: #1d4ed8; border-radius: 9999px; padding: 2px 10px; }

์ด๊ฑธ 5๊ฐœ ์ปดํฌ๋„ŒํŠธ์— ๊ฑธ์ณ ๋น„์Šทํ•œ CSS ๋ฅผ ๊ฐ์ž ๋งŒ๋“ค๋‹ค ๋ณด๋‹ˆ ์–ด๋А ์ˆœ๊ฐ„ card, post-card, user-card, study-card ๊ฐ™์€ ๋น„์Šทํ•˜์ง€๋งŒ ๋ฏธ๋ฌ˜ํ•˜๊ฒŒ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋“ค์ด ์ˆ˜์‹ญ ๊ฐœ ์ƒ๊ฒจ๋ฒ„๋ ธ์–ด.

์˜์ˆ™์ด "์นด๋“œ ๋‘ฅ๊ธ€๊ธฐ ์ข€ ์ค„์—ฌ์ฃผ์„ธ์š”" ๋ผ๊ณ  ํ•˜๋ฉด? border-radius ๋ฅผ ์–ด๋””์„œ ์–ด๋””๊นŒ์ง€ ๋ฐ”๊ฟ”์•ผ ํ• ์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ๋งŒ 30๋ถ„์ด ๊ฑธ๋ ค. ์˜์ˆ˜๋Š” ๋ฒŒ์จ "์™œ ์ด๋ ‡๊ฒŒ ์˜ค๋ž˜ ๊ฑธ๋ ค์š”?" ๋ผ๊ณ  ์žฌ์ด‰ํ•˜๊ณ  ์žˆ๊ณ .

์ด ํ˜ผ๋ˆ์„ ๋๋‚ด๋Ÿฌ ๋‚˜ํƒ€๋‚œ ๊ฒƒ์ด ๋ฐ”๋กœ Tailwind CSS ์˜ utility-first ์ ‘๊ทผ๋ฒ•์ด์•ผ.


๐Ÿ—๏ธ ๋น„์œ ๋กœ ๋จผ์ € ์ดํ•ดํ•˜๊ธฐ

๐Ÿค” ์ž ๊น, ๋จผ์ € ์ƒ๊ฐํ•ด๋ด
๋ ˆ๊ณ  ๋ธ”๋ก์œผ๋กœ ์ง‘์„ ์ง“๋Š” ๋ฐฉ๋ฒ•์—๋Š” ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์–ด. ์–ด๋–ค ๋ฐฉ๋ฒ•์ด ๋” ์œ ์—ฐํ•˜๊ณ  ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋†’์„๊นŒ?

๐Ÿงฑ ๋‘ ๊ฐ€์ง€ ๋ ˆ๊ณ  ์ „๋žต

[์ „๋žต A: ๋ฏธ๋ฆฌ ๋งŒ๋“ค์–ด์ง„ ์„ฑ ์„ธํŠธ]
๋ ˆ๊ณ  ์ œ์กฐ์‚ฌ๊ฐ€ "์„ฑ ํŒจํ‚ค์ง€", "์šฐ์ฃผ์„  ํŒจํ‚ค์ง€" ๋ฅผ ๋งŒ๋“ค์–ด์„œ ํŒ๋งค. ์•„๋ฆ„๋‹ต์ง€๋งŒ ๋‹ค๋ฅธ ํ˜•ํƒœ๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ํŒจํ‚ค์ง€๋ฅผ ๋œฏ์–ด๊ณ ์ณ์•ผ ํ•ด.

โ†’ ์ „ํ†ต CSS ์˜ ์ปดํฌ๋„ŒํŠธ๋ณ„ ํด๋ž˜์Šค (.card, .btn-primary, .modal-header) ๋ฐฉ์‹์ด์•ผ. ์ž˜ ๋งŒ๋“ค์–ด์ ธ ์žˆ์ง€๋งŒ, ๋งž์ง€ ์•Š์œผ๋ฉด ์ˆ˜์ˆ ์ด ํ•„์š”ํ•ด.

[์ „๋žต B: ์›์ž ๋ธ”๋ก๋“ค]
1x1 ๋ธ”๋ก, 2x1 ๋ธ”๋ก, ๋‘ฅ๊ทผ ๋ธ”๋ก... ๊ธฐ๋ณธ ๋‹จ์œ„ ๋ธ”๋ก๋งŒ ์ž”๋œฉ. ์ฒ˜์Œ์—” ์–ด์ƒ‰ํ•˜์ง€๋งŒ ๋ฌด์—‡์ด๋“  ์ž์œ ๋กญ๊ฒŒ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์–ด.

โ†’ Tailwind CSS ์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค (flex, p-6, rounded-xl, shadow-lg) ๋ฐฉ์‹์ด์•ผ.

๐Ÿ’ก ํ•œ ์ค„๋กœ ๊ธฐ์–ตํ•˜๊ธฐ
์ „ํ†ต CSS ๋Š” ์™„์„ฑ๋œ ์„ฑ ์„ธํŠธ, Tailwind ๋Š” ์›์ž ๋ธ”๋ก๋“ค์˜ ์ฐฝ๊ณ ๋‹ค. ์ฐฝ๊ณ ๊ฐ€ ์ฒ˜์Œ์—” ๋ณต์žกํ•ด ๋ณด์ด์ง€๋งŒ, ๊ฒฐ๊ตญ ๋” ๋งŽ์€ ๊ฒƒ์„ ๋” ๋น ๋ฅด๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด.


๐Ÿงฉ Utility-First ์ฒ ํ•™์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€

Tailwind CSS ์˜ ํ•ต์‹ฌ ์ฒ ํ•™์€ ๋”ฑ ํ•˜๋‚˜์•ผ:

"CSS ์†์„ฑ ํ•˜๋‚˜ = ํด๋ž˜์Šค ํ•˜๋‚˜"

flex ๋Š” display: flex; ๋งŒ ๋‹ด๋‹นํ•ด. p-6 ์€ padding: 1.5rem; ๋งŒ ๋‹ด๋‹นํ•ด. text-lg ๋Š” font-size: 1.125rem; ๋งŒ ๋‹ด๋‹นํ•ด.

์ด๋Ÿฐ ๋‹จ์ผ ์ฑ…์ž„์˜ ์›์ž์  ํด๋ž˜์Šค ๋“ค์„ HTML ์— ์กฐํ•ฉํ•ด์„œ UI ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์ด์•ผ.

๐Ÿ”ฌ Tailwind ํด๋ž˜์Šค ํ•ด๋ถ€ํ•™

<div class="flex items-center gap-4 rounded-xl bg-white p-6 shadow-lg">
  <!-- ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ์Šคํ„ฐ๋”” ์นด๋“œ -->
</div>
ํด๋ž˜์Šค์ƒ์„ฑ๋˜๋Š” CSS์—ญํ• 
flexdisplay: flexFlexbox ํ™œ์„ฑํ™”
items-centeralign-items: center์„ธ๋กœ ์ค‘์•™ ์ •๋ ฌ
gap-4gap: 1rem์ž์‹ ์š”์†Œ ๊ฐ„๊ฒฉ
rounded-xlborder-radius: 0.75rem๋‘ฅ๊ทผ ๋ชจ์„œ๋ฆฌ
bg-whitebackground-color: rgb(255 255 255)ํฐ ๋ฐฐ๊ฒฝ
p-6padding: 1.5rem๋‚ด๋ถ€ ์—ฌ๋ฐฑ
shadow-lgbox-shadow: 0 10px 15px -3px ...๊ทธ๋ฆผ์ž

์ด๊ฒŒ ์ „๋ถ€์•ผ. ๋ณต์žกํ•œ CSS ๊ทœ์น™ ์—†์ด, ํด๋ž˜์Šค ์ด๋ฆ„๋งŒ ๋ด๋„ ์Šคํƒ€์ผ์ด ๋จธ๋ฆฟ์†์— ๊ทธ๋ ค์ ธ.


โš–๏ธ ์ „ํ†ต์ ์ธ CSS vs Tailwind CSS

์ „ํ†ต CSS ์˜ ์„ธ ๊ฐ€์ง€ ๊ณ ํ†ต

1. ๋„ค์ด๋ฐ ์ง€์˜ฅ (Naming Hell)

/* ๐Ÿฃ ์˜์ฒ : ๋„๋Œ€์ฒด ์ด๊ฒŒ ๋งž๋Š” ์ด๋ฆ„์ธ๊ฐ€..? */
.study-card { }
.study-card-wrapper { }
.study-card-container { }        /* wrapper๋ž‘ container๋ž‘ ๋ญ๊ฐ€ ๋‹ฌ๋ผ..? */
.study-card__header { }
.study-card__header--active { }  /* BEM ์ง€์˜ฅ */

2. ์Šค์ฝ”ํ”„ ์˜ค์—ผ (Cascade Nightmare)

/* card.css */
.title { font-weight: bold; }
 
/* post.css */
.title { color: red; }  /* ๐Ÿ˜ฑ ์–ด๋А .title์ด ์ด๊ธธ์ง€ ์˜ˆ์ธก ๋ถˆ๊ฐ€ */

3. ๋ฐ๋“œ ์ฝ”๋“œ ๊ณตํฌ (Dead CSS)
6๊ฐœ์›” ์ „์— ๋งŒ๋“  .old-card-badge ํด๋ž˜์Šค... ์ง€๊ธˆ๋„ ์–ด๋”˜๊ฐ€์— ์“ฐ์ด๊ณ  ์žˆ์„๊นŒ? ์•„๋ฌด๋„ ๋ชฐ๋ผ. ์‚ญ์ œํ–ˆ๋‹ค๊ฐ€ UI ๊ฐ€ ๊นจ์ง€๋ฉด? ์˜์ˆ˜ํ•œํ…Œ ํ˜ผ๋‚œ๋‹ค.


Tailwind ๊ฐ€ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ๋„ค์ด๋ฐ ๊ณ ๋ฏผ Zero
ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์–ด. bg-blue-500, text-sm, font-bold โ€” ์ด๋ฆ„์ด ์ด๋ฏธ ์ •ํ•ด์ ธ ์žˆ์–ด.

2. ์Šค์ฝ”ํ”„ ์ถฉ๋Œ Zero
flex ๋Š” ํ•ญ์ƒ display: flex; ์•ผ. ์–ด๋А ํŒŒ์ผ์—์„œ ์จ๋„, ์–ด๋А ์ปดํฌ๋„ŒํŠธ์—์„œ ์จ๋„.

3. ๋ฐ๋“œ CSS Zero
์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ํด๋ž˜์Šค๋Š” ๋นŒ๋“œ ์‹œ ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋ผ. HTML ์— ์—†๋Š” ํด๋ž˜์Šค๋Š” CSS ๋ฒˆ๋“ค์— ํฌํ•จ๋˜์ง€ ์•Š์•„.


๐Ÿ’ป Before / After: ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ์นด๋“œ ์ปดํฌ๋„ŒํŠธ

์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ์Šคํ„ฐ๋”” ๊ทธ๋ฃน ์นด๋“œ๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ํ•ด๋ณด์ž.

โŒ ์ „ํ†ต CSS ๋ฐฉ์‹ (์ˆœ์ง„ํ•œ ์ฝ”๋“œ)

// ๐Ÿฃ ์˜์ฒ : "์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋˜๊ฒ ์ง€? CSS ๋ถ„๋ฆฌ๊ฐ€ ๋งž๋‹ค๊ณ  ๋ฐฐ์› ์œผ๋‹ˆ๊นŒ!"
 
// StudyCard.tsx
export function StudyCard({ title, memberCount, tag }: Props) {
  return (
    // className ์ด๋ฆ„ ์ง“๋Š” ๋ฐ๋งŒ 5๋ถ„...
    <div className="study-card">
      <div className="study-card__header">
        <span className="study-card__tag">{tag}</span>
        <h3 className="study-card__title">{title}</h3>
      </div>
      <div className="study-card__footer">
        <span className="study-card__member-count">
          ๋ฉค๋ฒ„ {memberCount}๋ช…
        </span>
      </div>
    </div>
  );
}
/* StudyCard.module.css */
/* ๐Ÿฃ ์˜์ฒ : CSS ํŒŒ์ผ ๋”ฐ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒŒ "๊น”๋”ํ•˜๋‹ค"๊ณ  ์ƒ๊ฐํ–ˆ๋˜ ์‹œ์ ˆ */
.study-card {
  background-color: white;
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  border: 1px solid #e5e7eb;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
 
.study-card__header {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
 
.study-card__tag {
  background-color: #dbeafe;
  color: #1d4ed8;
  font-size: 12px;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 9999px;
  width: fit-content;
}
 
.study-card__title {
  font-size: 18px;
  font-weight: 700;
  color: #111827;
  line-height: 1.4;
}
 
.study-card__footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
 
.study-card__member-count {
  font-size: 14px;
  color: #6b7280;
}

์ด ์ฝ”๋“œ๋Ÿ‰: TSX 21์ค„ + CSS 37์ค„ = 58์ค„, ํŒŒ์ผ 2๊ฐœ


โœ… Tailwind CSS ๋ฐฉ์‹ (ํ”„๋กœ ์ฝ”๋“œ)

// ๐Ÿฆ ์˜ํ˜ธ: "์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŒŒ์ผ ํ•˜๋‚˜์— ๋ชจ๋“  ์Šคํƒ€์ผ ์˜๋„๊ฐ€ ๋‹ด๊ฒจ์š”.
//           CSS ํŒŒ์ผ ์—ด ํ•„์š” ์—†์ด HTML๋งŒ ๋ด๋„ UI๊ฐ€ ๊ทธ๋ ค์ง€์ฃ ."
 
// StudyCard.tsx
export function StudyCard({ title, memberCount, tag }: Props) {
  return (
    <div className="flex flex-col gap-3 rounded-xl border border-gray-200 bg-white p-5 shadow-md">
      <div className="flex flex-col gap-2">
        {/* ํƒœ๊ทธ: ํŒŒ๋ž€ ๋ฐฐ์ง€ */}
        <span className="w-fit rounded-full bg-blue-100 px-3 py-0.5 text-xs font-semibold text-blue-700">
          {tag}
        </span>
        {/* ์ œ๋ชฉ */}
        <h3 className="text-lg font-bold leading-snug text-gray-900">
          {title}
        </h3>
      </div>
      <div className="flex items-center justify-between">
        <span className="text-sm text-gray-500">๋ฉค๋ฒ„ {memberCount}๋ช…</span>
      </div>
    </div>
  );
}

์ด ์ฝ”๋“œ๋Ÿ‰: TSX ํŒŒ์ผ ํ•˜๋‚˜์— 18์ค„, ํŒŒ์ผ 1๊ฐœ


๐Ÿ“Š ์ง์ ‘ ๋น„๊ต

๊ธฐ์ค€์ „ํ†ต CSSTailwind
ํŒŒ์ผ ์ˆ˜2๊ฐœ (TSX + CSS)1๊ฐœ (TSX)
์ฝ”๋“œ๋Ÿ‰58์ค„18์ค„
๋„ค์ด๋ฐ ๊ณ ๋ฏผ๋งค์šฐ ๋†’์Œ์—†์Œ
์Šคํƒ€์ผ ์œ„์น˜CSS ํŒŒ์ผ (๋ถ„๋ฆฌ)JSX (ํ†ตํ•ฉ)
์‚ญ์ œ ์‹œ ๋ฐ๋“œ ์ฝ”๋“œ๋‚จ์„ ์œ„ํ—˜ ์žˆ์Œ์ž๋™ ์ œ๊ฑฐ
์ˆ˜์ • ์‹œ ํŒŒ์ผ ์ด๋™ํ•„์š”๋ถˆํ•„์š”

๐Ÿšจ ์˜์ฒ ์ด๊ฐ€ ํ”ํžˆ ์ €์ง€๋ฅด๋Š” ์‹ค์ˆ˜๋“ค

์‹ค์ˆ˜ 1: ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ด๋ž‘ ํ—ท๊ฐˆ๋ฆฌ๊ธฐ

{/* ๐Ÿฃ ์˜์ฒ : "์ด๊ฒŒ ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ด๋ž‘ ๋ญ๊ฐ€ ๋‹ฌ๋ผ์š”?" */}
 
{/* โŒ ์ธ๋ผ์ธ ์Šคํƒ€์ผ โ€” hover, ๋ฐ˜์‘ํ˜• ๋ถˆ๊ฐ€! */}
<div style={{ padding: '24px', backgroundColor: 'white', borderRadius: '12px' }}>
 
{/* โœ… Tailwind โ€” hover:, md:, dark: ๊ฐ™์€ ๋ณ€ํ˜•(variant) ์‚ฌ์šฉ ๊ฐ€๋Šฅ! */}
<div className="p-6 bg-white rounded-xl hover:shadow-lg md:p-8 dark:bg-gray-800">

๐Ÿ’ก ํ•ต์‹ฌ ์ฐจ์ด: ์ธ๋ผ์ธ ์Šคํƒ€์ผ์€ "์ง€๊ธˆ ์ด ์ƒํƒœ๋งŒ" ์ ์šฉ. Tailwind ๋Š” hover:, md:, dark: ๊ฐ™์€ variant(๋ณ€ํ˜•) ์„ ๋ถ™์—ฌ์„œ ์กฐ๊ฑด๋ถ€ ์Šคํƒ€์ผ์ด ๊ฐ€๋Šฅํ•ด.

์‹ค์ˆ˜ 2: @apply ๋‚จ์šฉ

/* โŒ ์˜์ฒ ์˜ ์˜คํ•ด: "ํด๋ž˜์Šค๊ฐ€ ๋„ˆ๋ฌด ๊ธธ๋ฉด @apply๋กœ ๋ฌถ์œผ๋ฉด ๋˜๊ฒ ์ง€!" */
.my-card {
  @apply flex flex-col gap-3 rounded-xl border border-gray-200 bg-white p-5 shadow-md;
}
{/* ๐Ÿฆ ์˜ํ˜ธ: "์˜์ฒ  ๋‹˜, @apply๋Š” ๋งˆ์ง€๋ง‰ ์ˆ˜๋‹จ์ด์—์š”.
    ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด Tailwind์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ธ
    '์ฝ”๋“œ์™€ ์Šคํƒ€์ผ์˜ co-location'์ด ์‚ฌ๋ผ์ ธ์š”." */}

์˜ฌ๋ฐ”๋ฅธ ํŒ๋‹จ ๊ธฐ์ค€:

  • ๊ฐ™์€ ํด๋ž˜์Šค ์กฐํ•ฉ์ด 3๊ณณ ์ด์ƒ์—์„œ ๋ฐ˜๋ณต๋œ๋‹ค โ†’ React ์ปดํฌ๋„ŒํŠธ๋กœ ์ถ”์ถœ
  • ์ปดํฌ๋„ŒํŠธ ์ถ”์ถœ์ด ๋ถˆ๊ฐ€ํ•œ ์ƒํ™ฉ์ด๋‹ค โ†’ ๊ทธ๋•Œ๋งŒ @apply ๊ณ ๋ ค

์‹ค์ˆ˜ 3: ํด๋ž˜์Šค ์ •๋ ฌ ๋ฌด์‹œ

{/* ๐Ÿฃ ์˜์ฒ : ํด๋ž˜์Šค ์ˆœ์„œ๋Š” ์•„๋ฌด๋ž˜๋„ ์ƒ๊ด€์—†๊ฒ ์ง€~ */}
<div className="shadow-md p-5 flex rounded-xl bg-white gap-3 flex-col border border-gray-200">
 
{/* โœ… ์˜ํ˜ธ๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ์ˆœ์„œ: ๋ ˆ์ด์•„์›ƒ โ†’ ํฌ๊ธฐ โ†’ ๊ฐ„๊ฒฉ โ†’ ๋ฐฐ๊ฒฝ โ†’ ํ…Œ๋‘๋ฆฌ โ†’ ํšจ๊ณผ */}
<div className="flex flex-col gap-3 rounded-xl border border-gray-200 bg-white p-5 shadow-md">

๐Ÿ“Œ Prettier + prettier-plugin-tailwindcss ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํด๋ž˜์Šค ์ •๋ ฌ์ด ์ž๋™์œผ๋กœ ๋˜๋‹ˆ๊นŒ, ๋ฐ˜๋“œ์‹œ ์„ค์น˜ํ•ด๋‘์ž!


๐Ÿ ์ด๋ฒˆ์— ๋ฐฐ์šด ๋‚ด์šฉ ์ด์ •๋ฆฌ

๊ฐœ๋…ํ•ต์‹ฌ ์š”์•ฝ
Utility-FirstCSS ์†์„ฑ ํ•˜๋‚˜ = ํด๋ž˜์Šค ํ•˜๋‚˜. ์›์ž์  ๋‹จ์œ„๋กœ ์กฐํ•ฉ
vs ์ „ํ†ต CSS๋„ค์ด๋ฐ ์ง€์˜ฅ, ์Šค์ฝ”ํ”„ ์ถฉ๋Œ, ๋ฐ๋“œ ์ฝ”๋“œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐ
vs ์ธ๋ผ์ธ ์Šคํƒ€์ผhover/๋ฐ˜์‘ํ˜•/๋‹คํฌ๋ชจ๋“œ ๊ฐ™์€ variant ์ ์šฉ ๊ฐ€๋Šฅ
@apply๋‚จ์šฉ ๊ธˆ์ง€. 3๊ณณ ์ด์ƒ ๋ฐ˜๋ณต ์‹œ React ์ปดํฌ๋„ŒํŠธ ์ถ”์ถœ ์šฐ์„ 
ํ•ต์‹ฌ ์ด์ ํŒŒ์ผ ๊ฐ„ ์ด๋™ ์—†์ด HTML ๋งŒ ๋ณด๋ฉด ์Šคํƒ€์ผ์ด ๊ทธ๋ ค์ง

๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. ์˜์ฒ ์ด๊ฐ€ hover ์ƒํƒœ์—์„œ๋งŒ ๋ฐฐ๊ฒฝ์ƒ‰์„ ๋ฐ”๊พธ๊ณ  ์‹ถ๋‹ค. ๋‹ค์Œ ์ค‘ ์˜ฌ๋ฐ”๋ฅธ Tailwind ์ฝ”๋“œ๋Š”?

โ‘  <div style={{ ':hover': { backgroundColor: 'blue' } }}>
โ‘ก <div className="bg-blue-500:hover">
โ‘ข <div className="hover:bg-blue-500">
โ‘ฃ <div className="bg-blue-500 bg-blue-700">

โœ… ์ •๋‹ต: โ‘ข hover:bg-blue-500

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: Tailwind ์˜ variant ์‹œ์Šคํ…œ์€ {variant}:{utility} ํ˜•ํƒœ์•ผ. hover:bg-blue-500 ์€ Tailwind ๊ฐ€ hover\:bg-blue-500:hover { background-color: ... } ๋ผ๋Š” CSS ๋ฅผ ์ƒ์„ฑํ•ด์ค˜. ๋งˆ์น˜ ํด๋ž˜์Šค ์ด๋ฆ„ ์•ž์— ์ƒํƒœ ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์ด๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ง๊ด€์ ์ด์ง€.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: โ‘  ์€ ์ธ๋ผ์ธ ์Šคํƒ€์ผ๋กœ hover ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์—†์–ด. CSS ๋Š” JS ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ์•ผ. โ‘ก ์ฒ˜๋Ÿผ bg-blue-500:hover ์ˆœ์„œ๋Š” Tailwind ๋ฌธ๋ฒ•์ด ์•„๋‹ˆ์•ผ. ํ•ญ์ƒ variant ๊ฐ€ ์•ž์— ์™€. โ‘ฃ ๋Š” ๋‘ ๋ฐฐ๊ฒฝ์ƒ‰์„ ๋™์‹œ์— ์„ ์–ธํ•˜๋Š” ๊ฑด๋ฐ, CSS ์šฐ์„ ์ˆœ์œ„์— ๋”ฐ๋ผ ํ›„์ž๊ฐ€ ์ด๊ธฐ์ง€๋งŒ hover ์ƒํƒœ ์ œ์–ด๋Š” ์•ˆ ๋ผ.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: {์ƒํ™ฉ}:{์Šคํƒ€์ผ} โ€” ์ƒํ™ฉ์ด ๋จผ์ €, ์Šคํƒ€์ผ์ด ๋‚˜์ค‘. "hover ํ•  ๋•Œ bg-blue-500 ์ค˜!" ๋ฅผ ์ฝ”๋“œ๋กœ ์“ฐ๋ฉด hover:bg-blue-500.

Q2. ์˜์ˆ˜๊ฐ€ "์˜์ฒ  ๋‹˜, CSS ํŒŒ์ผ์ด ๋„ˆ๋ฌด ๋งŽ์•„์„œ ์ˆ˜์ •์ด ํž˜๋“ค์–ด์š”. Tailwind ์“ฐ๋ฉด ์–ด๋–ค ์ด์ ์ด ์žˆ์ฃ ?"๋ผ๊ณ  ๋ฌผ์—ˆ๋‹ค. ๊ฐ€์žฅ ํ•ต์‹ฌ์ ์ธ ๋‹ต๋ณ€์€?

โœ… ์ •๋‹ต: "์Šคํƒ€์ผ์ด HTML ๊ณผ ๊ณต์กด(co-location)ํ•ด์„œ, ์ปดํฌ๋„ŒํŠธ ํŒŒ์ผ ํ•˜๋‚˜๋งŒ ๋ณด๋ฉด ๋ชจ๋“  ์Šคํƒ€์ผ ์˜๋„๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CSS ํŒŒ์ผ ์ฐพ์„ ์ผ์ด ์—†์–ด์š”."

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: Tailwind ์˜ ์ตœ๋Œ€ ๊ฐ•์ ์€ co-location โ€” ์Šคํƒ€์ผ์ด HTML/JSX ์™€ ๊ฐ™์€ ํŒŒ์ผ์— ์žˆ์–ด์„œ ์–ด๋””์„œ ์–ด๋–ค ์Šคํƒ€์ผ์ด ์˜ค๋Š”์ง€ ์ถ”์ ์ด ํ•„์š” ์—†์–ด. ๋˜ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ญ์ œํ•˜๋ฉด ๊ทธ ์•ˆ์˜ ํด๋ž˜์Šค๋„ ํ•จ๊ป˜ ์‚ฌ๋ผ์ ธ์„œ ๋ฐ๋“œ CSS ๊ฐ€ ์ƒ๊ธฐ์ง€ ์•Š์•„.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: "ํด๋ž˜์Šค ์ˆ˜๊ฐ€ ์ค„์–ด๋“ ๋‹ค"๋Š” ํ‹€๋ ค. ์˜คํžˆ๋ ค ํด๋ž˜์Šค ์ˆ˜๋Š” ๋Š˜์–ด๋‚  ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ ๊ฐ ํด๋ž˜์Šค๊ฐ€ ๋‹จ์ผ ์ฑ…์ž„์„ ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์ถ”์ ๊ณผ ์ˆ˜์ •์ด ์‰ฌ์›Œ์ง€๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด์•ผ.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "CSS ํŒŒ์ผ = ๋ณด๋ฌผ์ฐพ๊ธฐ". Tailwind ๋Š” ๋ณด๋ฌผ์ง€๋„(์Šคํƒ€์ผ) ๋ฅผ ๋ณด๋ฌผ ์ƒ์ž(์ปดํฌ๋„ŒํŠธ) ์•ˆ์— ๊ฐ™์ด ๋„ฃ์–ด๋‘ฌ.

Q3. ์˜์ฒ ์ด๊ฐ€ ๊ฐ™์€ ์นด๋“œ ์Šคํƒ€์ผ์„ 10๊ตฐ๋ฐ์—์„œ ์“ฐ๊ณ  ์žˆ์–ด์„œ @apply ๋กœ ๋ฌถ์œผ๋ ค๊ณ  ํ•œ๋‹ค. ์˜ํ˜ธ๊ฐ€ ๋Œ€์‹  ์ œ์•ˆํ•  ์ ‘๊ทผ๋ฒ•์€?

โœ… ์ •๋‹ต: React ์ปดํฌ๋„ŒํŠธ๋กœ ์ถ”์ถœํ•œ๋‹ค โ€” <StudyCard /> ๊ฐ™์€ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํด๋ž˜์Šค๋ฅผ ์บก์Аํ™”.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: Tailwind ๊ณต์‹ ๋ฌธ์„œ๋„ ๊ฐ•์กฐํ•˜๋Š” ์›์น™ โ€” "๋ฐ˜๋ณต์„ ์ค„์ด๋Š” ๊ฐ€์žฅ ์ข‹์€ ๋ฐฉ๋ฒ•์€ ์ปดํฌ๋„ŒํŠธ ์ถ”์ถœ์ด์ง€, @apply ๊ฐ€ ์•„๋‹ˆ๋‹ค." @apply ๋Š” Tailwind ์˜ co-location ์ด์ ์„ ๋ฌด๋„ˆ๋œจ๋ฆฌ๊ณ , ๊ฒฐ๊ตญ ์ „ํ†ต CSS ์˜ ๋‹จ์ ์ธ "์Šคํƒ€์ผ์ด ์–ด๋”” ์žˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค" ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ๋งŒ๋“ค์–ด.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: @apply ๊ฐ€ ์™„์ „ ๋‚˜์œ ๊ฒƒ ์€ ์•„๋‹ˆ์•ผ. HTML/JSX ๊ฐ€ ์•„๋‹Œ ์จ๋“œํŒŒํ‹ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ†ตํ•ฉ์ด๋‚˜ ๊ธ€๋กœ๋ฒŒ base ์Šคํƒ€์ผ ์ž‘์„ฑ ์‹œ์—” ์ ์ ˆํžˆ ์“ธ ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ ์ปดํฌ๋„ŒํŠธ ์Šค์ฝ”ํ”„ ์•ˆ์—์„œ ๋ฐ˜๋ณต์„ ์ œ๊ฑฐํ•˜๋Š” ์šฉ๋„๋กœ๋Š” ์“ฐ์ง€ ๋ง์ž.
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: "๋ฐ˜๋ณต๋˜๋ฉด ์ปดํฌ๋„ŒํŠธ๋กœ, ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉด ๊ทธ๋•Œ @apply."

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

์˜ค๋Š˜์€ Tailwind ๋ฅผ ์ฒ˜์Œ ์ œ๋Œ€๋กœ ํŒŒ๋ดค๋‹ค. ์†”์งํžˆ ๋งํ•˜๋ฉด, ์˜ˆ์ „์— "ํด๋ž˜์Šค ๋„ˆ๋ฌด ๋งŽ์•„์„œ ๋ชป ์“ฐ๊ฒ ๋‹ค" ๊ณ  ํˆฌ๋œ๊ฑฐ๋ ธ๋˜ ๊ฒŒ ์ข€ ๋ถ€๋„๋Ÿฝ๋‹ค.

์˜ํ˜ธ ๋‹˜์ด "CSS ํŒŒ์ผ์„ ๋ณ„๋„๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒŒ ๊ผญ ๊น”๋”ํ•œ ๊ฒŒ ์•„๋‹ˆ์—์š”. ๋ณด๋ฌผ์„ ๋”ฐ๋กœ ์ˆจ๊ฒจ๋‘๋Š” ๊ฒƒ๋ฟ์ด์—์š”." ๋ผ๊ณ  ํ•˜์…จ๋Š”๋ฐ, ์ด ๋ง์ด ๋จธ๋ฆฟ์†์—์„œ ๊ณ„์† ๋งด๋ˆ๋‹ค.

๐Ÿ’ก ์˜ค๋Š˜์˜ ๊ตํ›ˆ: "๊ธธ์–ด ๋ณด์ด๋Š” ํด๋ž˜์Šค ๋‚˜์—ด์ด ์‚ฌ์‹ค์€ ๊ฐ€์žฅ ์ •์งํ•œ ์Šคํƒ€์ผ ์„ ์–ธ์ด๋‹ค. ์ˆจ๊ฒจ์ง„ CSS ๋Š” ์—†๋‹ค."

์‚ฌ์‹ค prettier-plugin-tailwindcss ์„ค์น˜ํ•˜๊ณ  ๋‚˜๋‹ˆ๊นŒ ํด๋ž˜์Šค ์ •๋ ฌ๋„ ์ž๋™์œผ๋กœ ๋˜๋”๋ผ. ์ด๊ฑฐ ์ข€ ๋” ์ผ์ฐ ์•Œ์•˜์œผ๋ฉด ์ข‹์•˜์„ ํ…๋ฐ. ์•ž์œผ๋กœ Flexbox ๋ž‘ Grid ๋ฅผ Tailwind ๋กœ ์–ด๋–ป๊ฒŒ ์“ฐ๋Š”์ง€๋„ ์ตํ˜€์•ผ์ง€. ์˜ค๋Š˜ ์ €๋…์€ ์น˜ํ‚จ ์‹œ์ผœ๋จน์œผ๋ฉด์„œ ์œ ํŠœ๋ธŒ ์ข€ ๋ด์•ผ๊ฒ ๋‹ค. ๐Ÿ˜Š


๐Ÿ”— ๋” ์•Œ์•„๋ณด๊ธฐ