๐Ÿ’…CSS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์Šคํƒ€์ผ๋ง์˜ ์ง„ํ™” : ๋„ค์ดํ‹ฐ๋ธŒ CSS๋ถ€ํ„ฐ Zero-Runtime๊นŒ์ง€

zizonyoungjunยท2024๋…„ 10์›” 12์ผ
3
post-custom-banner

๐Ÿง‘โ€๐Ÿ’ป์ด ๊ธ€์€ ํ•„์ž์˜ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์— ์‚ฌ์šฉํ•  CSS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ•™์Šตํ•˜๊ณ , ๊ทธ ์ค‘ ์–ด๋–ค ๊ฒƒ์„ ์‚ฌ์šฉํ• ์ง€๋ฅผ ๊ณ ๋ฏผํ•˜๋Š” ๊ณผ์ •์— ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

1. CSS์˜ ๋“ฑ์žฅ

HTML์ด ์ฒ˜์Œ ๋“ฑ์žฅํ–ˆ์„ ๋•Œ, ์›น ํŽ˜์ด์ง€์˜ ๋””์ž์ธ๊ณผ ๋ ˆ์ด์•„์›ƒ์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ์ œํ•œ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์›น ๊ฐœ๋ฐœ์ž๋Š” HTML ํƒœ๊ทธ์— ์ง์ ‘ ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๋Š” ์ธ๋ผ์ธ ์Šคํƒ€์ผ ๋ฐฉ์‹์„ ์ฃผ๋กœ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ, ์ด ๋ฐฉ์‹์€ ๋ชจ๋“  ์Šคํƒ€์ผ ์ •๋ณด๋ฅผ ๊ฐ ์š”์†Œ์— ์ง์ ‘ ๊ธฐ์ˆ ํ•˜๋Š” ๋ฐฉ์‹์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฒ„ํŠผ์— ํŒŒ๋ž€์ƒ‰ ๋ฐฐ๊ฒฝ๊ณผ ํฐ์ƒ‰ ํ…์ŠคํŠธ๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ์•„๋ž˜ ์ฝ”๋“œ์™€ ๊ฐ™์ด HTML ํƒœ๊ทธ ๋‚ด๋ถ€์— ์Šคํƒ€์ผ์„ ์ผ์ผ์ด ์ž‘์„ฑํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

<!-- css ๋“ฑ์žฅ ์ด์ „, inline style ๋กœ ์ž‘์„ฑ๋œ HTML-->
<div style="background-color: blue; color: white; padding: 10px; border-radius: 5px;">
  Click Me
</div>

์ด๋Ÿฐ ๋ฐฉ์‹์€ ์ดˆ๊ธฐ ์›น์—์„œ๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ์œ ์šฉํ–ˆ์ง€๋งŒ, ์›น์‚ฌ์ดํŠธ๊ฐ€ ์ ์  ๋” ๋ณต์žกํ•ด์ง์— ๋”ฐ๋ผ ์ฝ”๋“œ์˜ ์ค‘๋ณต๊ณผ ์œ ์ง€๋ณด์ˆ˜์˜ ์–ด๋ ค์›€์ด๋ผ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ ์Šคํƒ€์ผ์„ ์—ฌ๋Ÿฌ ๊ณณ์— ์ ์šฉํ•˜๋ ค๋ฉด HTML ๊ณณ๊ณณ์— ์Šคํƒ€์ผ์„ ๋ฐ˜๋ณตํ•ด์„œ ์ž‘์„ฑํ•ด์•ผ ํ–ˆ๊ณ , ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ ํ•ด๋‹น ์Šคํƒ€์ผ์„ ์ˆ˜์ž‘์—…์œผ๋กœ ์ˆ˜์ •ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ธ๋ผ์ธ ์Šคํƒ€์ผ์€ ๋ฌธ์„œ ๊ตฌ์กฐ์™€ ๋””์ž์ธ์ด ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์–ด ์‹œ๊ฐ์  ์Šคํƒ€์ผ๊ณผ ์ฝ˜ํ…์ธ ๋ฅผ ๋…๋ฆฝ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์–ด๋ ต๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ๊ฒƒ์ด CSS(Cascading Style Sheets)์ž…๋‹ˆ๋‹ค. CSS๋Š” ์›น ํŽ˜์ด์ง€์˜ ์Šคํƒ€์ผ์„ ์ค‘์•™์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜์—ฌ, HTML ๋ฌธ์„œ์˜ ๊ตฌ์กฐ์™€ ์Šคํƒ€์ผ์„ ๋ถ„๋ฆฌํ•˜๋Š” ํ˜์‹ ์„ ๊ฐ€์ ธ์™”์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” HTML ์š”์†Œ์— ๋Œ€ํ•œ ์Šคํƒ€์ผ ๊ทœ์น™์„ ๋ณ„๋„์˜ CSS ํŒŒ์ผ์— ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๊ณ , ์ด๋ ‡๊ฒŒ ๋ถ„๋ฆฌ๋œ ์Šคํƒ€์ผ ๊ทœ์น™์€ ์ผ๊ด€์„ฑ ์žˆ๋Š” ๋””์ž์ธ๊ณผ ํšจ์œจ์ ์ธ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.

<!-- HTML ํŒŒ์ผ -->
<div class="button">Click Me</div>

<!-- CSS ํŒŒ์ผ -->
.button {
  background-color: blue;
  color: white;
  padding: 10px;
  border-radius: 5px;
}

๊ทธ๋Ÿฌ๋‚˜ CSS๋Š” ํฌ๊ฒŒ ๋‘๊ฐ€์ง€์˜ ํ•œ๊ณ„์ ์ด ์กด์žฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์šฐ์„ ,Global Scope๋กœ ์ธํ•ด ์ „์—ญ์ ์œผ๋กœ ์Šคํƒ€์ผ์ด ์ ์šฉ๋˜๋ฉด์„œ ํด๋ž˜์Šค ์ด๋ฆ„ ์ถฉ๋Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋™์ผํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜๋ฉด ์˜๋„ํ•˜์ง€ ์•Š์€ ์Šคํƒ€์ผ์ด ์ ์šฉ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์งˆ์ˆ˜๋ก ์ด๋Ÿฌํ•œ ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์•„์ง‘๋‹ˆ๋‹ค. ๋˜ํ•œ Specificity(์šฐ์„ ์ˆœ์œ„) ๊ทœ์น™์€ ์Šคํƒ€์ผ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ธฐ์ค€์ด ๋ณต์žกํ•˜์—ฌ, ํŠน์ • ์Šคํƒ€์ผ์„ ๋ฎ์–ด์“ฐ๊ฑฐ๋‚˜ ์šฐ์„  ์ ์šฉ๋˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด !important๋‚˜ ๋งค์šฐ ๊ธด ์„ ํƒ์ž ์ฒด์ธ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ค์›Œ์ง€๊ณ , ์Šคํƒ€์ผ๋ง ์ฝ”๋“œ๊ฐ€ ๋น„ํšจ์œจ์ ์œผ๋กœ ์ž‘์„ฑ๋˜๋Š” ํ•œ๊ณ„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

1.5 Specificity ๋ฌธ์ œ

Specificity(์šฐ์„ ์ˆœ์œ„)๋Š” CSS์—์„œ ์—ฌ๋Ÿฌ ์Šคํƒ€์ผ ๊ทœ์น™์ด ๋™์ผํ•œ ์š”์†Œ์— ์ ์šฉ๋  ๋•Œ, ์–ด๋–ค ์Šคํƒ€์ผ์ด ์šฐ์„  ์ ์šฉ๋ ์ง€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ทœ์น™์ž…๋‹ˆ๋‹ค. Specificity ๋ฌธ์ œ๋Š” ์ด๋Ÿฌํ•œ ์šฐ์„ ์ˆœ์œ„ ๊ณ„์‚ฐ์ด ๋ณต์žกํ•ด์ง€๋ฉด์„œ, ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜๋„ํ•œ ๋Œ€๋กœ ์Šคํƒ€์ผ์„ ์‰ฝ๊ฒŒ ์กฐ์ž‘ํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€๋Š” ์ƒํ™ฉ์„ ์ง€์นญํ•ฉ๋‹ˆ๋‹ค.

Specificity ๊ณ„์‚ฐ ๋ฐฉ๋ฒ•

CSS์—์„œ Specificity๋Š” ์„ ํƒ์ž์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ ์ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ ์ˆ˜๊ฐ€ ๋†’์„์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์œผ๋ฉฐ, ์•„๋ž˜์˜ ๊ทœ์น™์— ๋”ฐ๋ผ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

  1. ์ธ๋ผ์ธ ์Šคํƒ€์ผ : 1000์ 
  2. ID ์„ ํƒ์ž : 100์ 
  3. ํด๋ž˜์Šค, ์†์„ฑ, ์˜์‚ฌ ํด๋ž˜์Šค ์„ ํƒ์ž : 10์ 
  4. ํƒœ๊ทธ, ์˜์‚ฌ ์š”์†Œ ์„ ํƒ์ž : 1์ 
  5. ์œ ๋‹ˆ๋ฒ„์„ค ์„ ํƒ์ž(*)์™€ ๊ฒฐํ•ฉ์ž(>, +, ~) : 0์ 
/* Specificity ์ ์ˆ˜ ๊ณ„์‚ฐ ์˜ˆ์‹œ*/
div {               /* 1์  */
  color: black;
}

.button {           /* 10์  */
  color: blue;
}

#primary {          /* 100์  */
  color: green;
}

style="color: red"  /* 1000์  (์ธ๋ผ์ธ ์Šคํƒ€์ผ) */

์œ„ ์˜ˆ์‹œ์—์„œ ๋™์ผํ•œ ์š”์†Œ์— div, .button, #primary, ๊ทธ๋ฆฌ๊ณ  ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ด ์ ์šฉ๋œ๋‹ค๋ฉด, ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ์ธ๋ผ์ธ ์Šคํƒ€์ผ์ด ์ตœ์ข…์ ์œผ๋กœ ์ ์šฉ๋˜์–ด ํ…์ŠคํŠธ ์ƒ‰์ƒ์ด ๋นจ๊ฐ„์ƒ‰์ด ๋ฉ๋‹ˆ๋‹ค.


2. SCSS (Sass)

CSS๊ฐ€ ๋” ๋ณต์žกํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ๊ด€๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€์ž, ์ด๋ฅผ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด SCSS๊ฐ€ ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. SCSS๋Š” CSS์˜ ๋‹จ์ˆœํ•จ์„ ์œ ์ง€ํ•˜๋ฉด์„œ๋„ ๋ณ€์ˆ˜, ์ค‘์ฒฉ, ๋ฏน์Šค์ธ๊ณผ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ CSS์˜ ๋ฐ˜๋ณต์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ๋” ๊ตฌ์กฐ์ ์ธ ์Šคํƒ€์ผ ์ž‘์„ฑ์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. SCSS๋Š” CSS๋กœ ์ปดํŒŒ์ผ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ, ์ด ์ ์ด ์ปดํŒŒ์ผ ๊ณผ์ •์ด๋ผ๋Š” ์ถ”๊ฐ€ ์ž‘์—…์„ ์š”๊ตฌํ•˜์ง€๋งŒ, ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

$primary-color: blue;

@mixin button-styles($color, $padding) {
  background-color: $color;
  padding: $padding;
  border: none;
  border-radius: 5px;
  color: white;
}

.button {
  @include button-styles(blue, 10px);
  background-color: $primary-color;
  color: white;
  padding: 10px;

  .icon {
    margin-right: 5px;
  }
}

.button-secondary {
  @include button-styles(green, 15px);
}

๋‹ค๋งŒ SCSS๋„ ์—ฌ์ „ํžˆ Specificity ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•˜๋ฉฐ, ์ค‘์ฒฉ๋œ ๊ทœ์น™์ด ๋งŽ์•„์งˆ์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„ ๊ด€๋ฆฌ๊ฐ€ ๋” ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, SCSS๋Š” ์ปดํŒŒ์ผ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐœ๋ฐœ ์†๋„๊ฐ€ ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ ๋””๋ฒ„๊น…์ด ๋” ์–ด๋ ค์›Œ์ง‘๋‹ˆ๋‹ค.


3. BEM (Block Element Modifier)

CSS ํด๋ž˜์Šค ์ด๋ฆ„์˜ ์ถฉ๋Œ ๋ฌธ์ œ์™€ ์ „์—ญ ์Šค์ฝ”ํ”„์˜ ํ•œ๊ณ„๋ฅผ ๊ทน๋ณตํ•˜๊ธฐ ์œ„ํ•ด ๋“ฑ์žฅํ•œ ๋ฐฉ๋ฒ•๋ก ์ด BEM(Block Element Modifier)์ž…๋‹ˆ๋‹ค. BEM์€ CSS ํด๋ž˜์Šค ์ด๋ฆ„์„ Block__Element--Modifier๋ผ๋Š” ๊ตฌ์กฐ์ ์ธ ๊ทœ์น™์— ๋”ฐ๋ผ ๋ช…๋ช…ํ•จ์œผ๋กœ์จ, ํด๋ž˜์Šค๋ฅผ ๋ณด๋‹ค ๋ชจ๋“ˆํ™”๋œ ๋ฐฉ์‹์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํด๋ž˜์Šค ์ด๋ฆ„ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ ๋ฐฉ์‹์— ๋งž์ถ˜ ์Šคํƒ€์ผ๋ง์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

.button__icon--small {
  width: 20px;
  height: 20px;
}

๊ทธ๋Ÿฌ๋‚˜ BEM์€ ํด๋ž˜์Šค ๋ช…๋ช… ๊ทœ์น™์„ ์—„๊ฒฉํ•˜๊ฒŒ ๋”ฐ๋ผ์•ผ ํ•˜๋ฉฐ, ํ”„๋กœ์ ํŠธ๊ฐ€ ๋ณต์žกํ•ด์งˆ์ˆ˜๋ก ํด๋ž˜์Šค ์ด๋ฆ„์ด ๊ธธ์–ด์ ธ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๊ธธ์–ด์ง„ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๋ฐ˜๋ณตํ•ด์„œ ์ž‘์„ฑํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์ฝ”๋“œ ์ƒ์‚ฐ์„ฑ์—๋„ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


4. CSS Modules

CSS์˜ ์ „์—ญ ์Šค์ฝ”ํ”„ ๋ฌธ์ œ๋ฅผ ๊ทผ๋ณธ์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด, 2015๋…„์—๋Š” CSS Modules๊ฐ€ ๋“ฑ์žฅํ–ˆ์Šต๋‹ˆ๋‹ค. CSS Modules๋Š” CSS ํŒŒ์ผ์„ ๋ชจ๋“ˆํ™”ํ•˜์—ฌ ๊ฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ณ ์œ ํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ฐ–๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๊ธ€๋กœ๋ฒŒ ์Šค์ฝ”ํ”„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ , ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ์Šคํƒ€์ผ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํ›จ์”ฌ ์šฉ์ดํ•ด์กŒ์Šต๋‹ˆ๋‹ค. CSS ํŒŒ์ผ์— ๊ณ ์œ ํ•œ ํ•ด์‹œ ๊ฐ’์„ ๋ถ€์—ฌํ•˜์—ฌ, ํด๋ž˜์Šค ์ด๋ฆ„ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๋ฉฐ, ์Šคํƒ€์ผ์„ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ์•ˆ์ „ํ•˜๊ฒŒ ์บก์Šํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

/* Button.module.css */
.button {
  background-color: blue;
  color: white;
}

// Button.jsx
import styles from './Button.module.css';

export default function Button() {
  return <button className={styles.button}>Click Me</button>;
}

๊ทธ๋Ÿฌ๋‚˜ CSS Modules๋Š” ๊ณ ์œ ํ•œ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐœ๋ฐœ ์ค‘ ๋””๋ฒ„๊น…์ด ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋ฐœ์ž๊ฐ€ CSS ํŒŒ์ผ์—์„œ ๋ช…์‹œํ•œ ์ด๋ฆ„๊ณผ ์‹ค์ œ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ ์šฉ๋˜๋Š” ์ด๋ฆ„์ด ๋‹ค๋ฅด๋ฏ€๋กœ, ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ง์ ‘ ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ฐพ์•„๋ณด๊ธฐ ๋ถˆํŽธํ•˜๋ฉฐ, CSS ๋””๋ฒ„๊น… ๋„๊ตฌ ์‚ฌ์šฉ ์‹œ ํ˜ผ๋ž€์„ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, CSS Modules๋Š” ๋ณ„๋„์˜ CSS ํŒŒ์ผ์„ ์œ ์ง€ํ•ด์•ผ ํ•˜๋ฏ€๋กœ, ์Šคํƒ€์ผ์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ๊ณผ ๋ถ„๋ฆฌ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์ ์ด ๋ฒˆ๊ฑฐ๋กœ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


5. CSS-In-JS

์ „ํ†ต์ ์ธ CSS ๋ฐฉ์‹์—์„œ๋Š” HTML ์š”์†Œ์— ํด๋ž˜์Šค๋ฅผ ๋ถ€์—ฌํ•˜๊ณ , ์™ธ๋ถ€ CSS ํŒŒ์ผ์—์„œ ํ•ด๋‹น ํด๋ž˜์Šค์— ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด ์ฃผ๋กœ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ React์™€ ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” ๊ฐ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž์ฒด์ ์œผ๋กœ UI์™€ ๋กœ์ง์„ ๊ด€๋ฆฌํ•˜๋ฏ€๋กœ, ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์Šคํƒ€์ผ์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ์ •์˜ํ•˜๋Š” ๋ฐฉ์‹์ด ๋” ์œ ๋ฆฌํ•œ ์ƒํ™ฉ์ด ๋งŽ์•„์กŒ์Šต๋‹ˆ๋‹ค.

CSS-In-JS๋Š” ์ด๋Ÿฌํ•œ ๋ฐฐ๊ฒฝ์—์„œ ํƒ„์ƒํ–ˆ์œผ๋ฉฐ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ ๋‚ด์—์„œ CSS๋ฅผ ์ž‘์„ฑํ•˜๊ณ , ์ƒํƒœ๋‚˜ props์— ๋”ฐ๋ผ ๋™์ ์œผ๋กœ ์Šคํƒ€์ผ์„ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปดํฌ๋„ŒํŠธ์™€ ์Šคํƒ€์ผ์˜ ๋ฐ€์ ‘ํ•œ ๊ฒฐํ•ฉ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๊ณ , ์Šคํƒ€์ผ์„ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. CSS-In-JS๋Š” ๋Ÿฐํƒ€์ž„์— ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜๊ณ  ์ ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— global scope ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ฉด์„œ๋„ ๋™์  ์Šคํƒ€์ผ๋ง์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€ํ‘œ์ ์ธ CSS-In-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ๋Š” styled-components์™€ Emotion์ด ์žˆ์Šต๋‹ˆ๋‹ค.

import styled from 'styled-components';

const Button = styled.button`
  background-color: ${(props) => (props.primary ? 'blue' : 'gray')};
  color: white;
  padding: 10px;
`;

export default function App() {
  return <Button primary>Click Me</Button>;
}

๊ทธ๋Ÿฌ๋‚˜ ๋Ÿฐํƒ€์ž„์—์„œ ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ์ €ํ•˜์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์œผ๋ฉฐ, ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์„ฑ๋Šฅ ๋ฌธ์ œ๊ฐ€ ๋‘๋“œ๋Ÿฌ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ, ์• ๋‹ˆ๋ฉ”์ด์…˜์ด๋‚˜ ์Šคํฌ๋กค๊ณผ ๊ฐ™์€ ๋ณต์žกํ•œ ๋™์ž‘์„ ์ž์ฃผ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ, ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜๊ณ  DOM์— ์ ์šฉํ•˜๋Š” ๊ณผ์ •์—์„œ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”๋ถˆ์–ด, CSS-In-JS๋Š” ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•˜๋ฉฐ, ๊ทธ๋กœ ์ธํ•ด ๋ฒˆ๋“ค ํฌ๊ธฐ๊ฐ€ ์ปค์ง€๋Š” ๋‹จ์ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.


6. Vanilla Extract (Zero-Runtime CSS-In-JS)

Vanilla Extract๋Š” Zero-Runtime CSS-In-JS์˜ ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๋กœ, ๋Ÿฐํƒ€์ž„์— ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜์ง€ ์•Š๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ•œ CSS ๊ด€๋ฆฌ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด CSS-In-JS ๋ฐฉ์‹์ด ๋Ÿฐํƒ€์ž„์—์„œ ๋™์ ์œผ๋กœ ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜๋ฉฐ ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Vanilla Extract๋Š” ๋นŒ๋“œ ํƒ€์ž„์— CSS ํŒŒ์ผ์„ ์ƒ์„ฑํ•จ์œผ๋กœ์จ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์—†๊ณ , TypeScript๋ฅผ ํ™œ์šฉํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜๋ฉด์„œ๋„ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค. ์Šคํƒ€์ผ๊ณผ ๋กœ์ง์ด ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜๋ฉด์„œ๋„ ๋Ÿฐํƒ€์ž„์—์„œ์˜ ๋น„์šฉ์„ ์ค„์ผ ์ˆ˜ ์žˆ์–ด, ๋ณต์žกํ•œ UI์—์„œ๋„ ๋†’์€ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// styles.css.ts
import { style } from '@vanilla-extract/css';

export const button = style({
  backgroundColor: 'blue',
  color: 'white',
  padding: '10px',
});

// Button.jsx
import * as styles from './styles.css';

export default function Button() {
  return <button className={styles.button}>Click Me</button>;
}

๊ทธ๋Ÿฌ๋‚˜ ๋™์  ์Šคํƒ€์ผ๋ง ๊ธฐ๋Šฅ์ด ์ œํ•œ์ ์ด๋ผ๋Š” ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋Ÿฐํƒ€์ž„์—์„œ ์Šคํƒ€์ผ์„ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹  ๋นŒ๋“œ ํƒ€์ž„์— ๋ชจ๋“  ์Šคํƒ€์ผ์ด ๋ฏธ๋ฆฌ ๊ณ„์‚ฐ๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ƒํƒœ์— ๋”ฐ๋ผ ์ฆ‰์‹œ ๋ณ€๊ฒฝํ•ด์•ผ ํ•˜๋Š” ๋™์  ์Šคํƒ€์ผ์„ ์ ์šฉํ•˜๋Š” ๋ฐ๋Š” ์–ด๋ ค์›€์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋นŒ๋“œ ๋‹จ๊ณ„์—์„œ ์ถ”๊ฐ€์ ์ธ ์„ค์ •์ด ํ•„์š”ํ•˜๋ฉฐ, ์ด๋ฅผ ์œ„ํ•ด Webpack์ด๋‚˜ Vite์™€ ๊ฐ™์€ ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ๋ณต์žก์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ์„ค์ •์ด ๋ณต์žกํ•ด์งˆ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํŠน์ • ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถ˜ ๋™์  ์Šคํƒ€์ผ๋ง์ด ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


6.5. CSS-in-JS vs Zero-Runtime CSS-in-JS

ํ•ต์‹ฌ ํŠน์ง• ๋น„๊ต

ํŠน์ง•CSS-in-JSZero-Runtime CSS-in-JSwho wins?
๋™์  ์Šคํƒ€์ผ๋ง์ƒํƒœ/props์— ๋”ฐ๋ผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์Šคํƒ€์ผ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ๋นŒ๋“œ ์‹œ์ ์— ์Šคํƒ€์ผ์ด ๊ฒฐ์ •๋˜์–ด ์ œํ•œ์ CSS-in-JS๊ฐ€ ๋” ์œ ์—ฐํ•˜์ง€๋งŒ, Zero-Runtime์ด ๋” ์„ฑ๋Šฅ์ด ์ข‹์Œ
์„ฑ๋Šฅ๋Ÿฐํƒ€์ž„์— ์„ฑ๋Šฅ ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ๋Ÿฐํƒ€์ž„์—์„œ ์Šคํƒ€์ผ ์ƒ์„ฑ ์—†์–ด ์„ฑ๋Šฅ ์ตœ์ ํ™”๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ Zero-Runtime์ด ๋” ๋‚˜์€ ์„ฑ๋Šฅ์„ ๋ณด์ž„
ํƒ€์ž… ์•ˆ์ „์„ฑ์ผ๋ฐ˜์ ์œผ๋กœ ํƒ€์ž… ์•ˆ์ „ํ•˜์ง€ ์•Š์ŒTypeScript ํ†ตํ•ฉ์œผ๋กœ ํƒ€์ž… ์•ˆ์ „์„ฑ ๋ณด์žฅZero-Runtime์ด ๋” ๋‚˜์€ ํƒ€์ž… ์•ˆ์ „์„ฑ ์ œ๊ณต
๋ฒˆ๋“ค ํฌ๊ธฐJavaScript ๋ฒˆ๋“ค ํฌ๊ธฐ ์ฆ๊ฐ€๋ฒˆ๋“ค ํฌ๊ธฐ ์ตœ์†Œํ™”, ์Šคํƒ€์ผ์€ ๋ณ„๋„ CSS ํŒŒ์ผ๋กœZero-Runtime์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ์ž‘์€ ๋ฒˆ๋“ค ํฌ๊ธฐ
SSR ํ˜ธํ™˜์„ฑSSR์—์„œ ์ค‘๋ณต ์Šคํƒ€์ผ ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋ŠฅSSR์— ์ตœ์ ํ™”, ์Šคํƒ€์ผ ์ค‘๋ณต ์—†์ŒZero-Runtime์ด SSR ํ˜ธํ™˜์„ฑ์ด ๋” ์ข‹์Œ

CSS-in-JS๋Š” ๋™์  ์Šคํƒ€์ผ๋ง์ด ์ค‘์š”ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ƒํƒœ ๊ธฐ๋ฐ˜ UI, ์กฐ๊ฑด๋ถ€ ๋ Œ๋”๋ง, ์‹ค์‹œ๊ฐ„ ์‚ฌ์šฉ์ž ์ธํ„ฐ๋ž™์…˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋Œ€ํ™”ํ˜• ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ๋ฐ˜์‘ํ˜• ์›น์‚ฌ์ดํŠธ์—์„œ๋Š” CSS-in-JS๊ฐ€ ๋” ํฐ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์—ฌ ๋น ๋ฅธ ๊ฐœ๋ฐœ๊ณผ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

๋ฐ˜๋ฉด, Zero-Runtime CSS-in-JS๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™”๊ฐ€ ์ค‘์š”ํ•œ ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ํŠนํžˆ, ๋Œ€๊ทœ๋ชจ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ ์—†์ด ๊ณ ์„ฑ๋Šฅ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ, Vanilla Extract์™€ ๊ฐ™์€ ๋ฐฉ์‹์ด ๋” ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ TypeScript์™€์˜ ํ†ตํ•ฉ์„ ํ†ตํ•ด ์•ˆ์ •์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋Œ€๊ทœ๋ชจ ํŒ€ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ ์˜ค๋ฅ˜๋ฅผ ์ค„์ด๊ณ , ์•ˆ์ •์ ์ธ ์ฝ”๋“œ๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๋ถˆ๊ฝƒ ํŠ€๋Š” ๋Œ€๊ฒฐ ์†์—์„œ ์Šคํƒ€์ผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ์™•๊ด€์„ ์ฐจ์ง€ํ•  ์ž๋Š” ๋ˆ„๊ตฌ์ธ๊ฐ€ ..

The Winner is โ€ฆ

post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€