August 17, 2025

๐ŸŽญ ์ „์—ญ CSS ์˜ค์—ผ: ์˜ˆ์ธก ๋ถˆ๊ฐ€๋Šฅํ•œ ์Šคํƒ€์ผ ์ถฉ๋Œ๊ณผ ์œ ์ง€๋ณด์ˆ˜ ์•…๋ชฝ

React
CSS
์•„ํ‚คํ…์ฒ˜
์ปดํฌ๋„ŒํŠธ
๋„ค์ด๋ฐ
Lint/Formatter
์„ฑ๋Šฅ
์›นํ‘œ์ค€

Summary

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

Why Wrong?

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

How to Fix?

CSS Modules, Styled Components, Shadow DOM ๋“ฑ์˜ ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ CSS ์Šค์ฝ”ํ”„๋ฅผ ์ปดํฌ๋„ŒํŠธ ๋‹จ์œ„๋กœ ์ œํ•œํ•˜๊ณ  ์Šคํƒ€์ผ ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. CSS Modules๋Š” ๊ฐ CSS ํด๋ž˜์Šค ์ด๋ฆ„์„ ๊ณ ์œ ํ•˜๊ฒŒ ์ƒ์„ฑํ•˜์—ฌ ์ปดํฌ๋„ŒํŠธ๋ณ„๋กœ ์Šคํƒ€์ผ์„ ๊ฒฉ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. Styled Components๋Š” ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— CSS๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•˜์—ฌ ์Šคํƒ€์ผ๊ณผ ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋†’์ด๊ณ , props๋ฅผ ํ†ตํ•ด ๋™์ ์ธ ์Šคํƒ€์ผ์„ ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. Shadow DOM์€ ์›น ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์„ ์บก์Аํ™”ํ•˜์—ฌ ์™ธ๋ถ€ ์Šคํƒ€์ผ์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, BEM(Block, Element, Modifier)๊ณผ ๊ฐ™์€ CSS ๋ฐฉ๋ฒ•๋ก ์„ ์ ์šฉํ•˜์—ฌ CSS ํด๋ž˜์Šค ๋„ค์ด๋ฐ ๊ทœ์น™์„ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์œ ์ง€ํ•˜๊ณ  ์Šคํƒ€์ผ ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. CSS-in-JS ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ์‹ ์ค‘ํ•˜๊ฒŒ ์„ ํƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Before Code (Bad)

/* global.css */
.button {
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border: none;
  cursor: pointer;
}

/* ComponentA.css */
.button {
  background-color: red; /* ์˜๋„์น˜ ์•Š์€ ์Šคํƒ€์ผ ์žฌ์ •์˜ */
}

/* ComponentB.css */
.button {
  font-size: 1.2em; /* ๋˜ ๋‹ค๋ฅธ ์˜๋„์น˜ ์•Š์€ ์Šคํƒ€์ผ ์žฌ์ •์˜ */
}
```
```jsx
// ComponentA.jsx
import './ComponentA.css';

function ComponentA() {
  return <button className="button">Button A</button>;
}

// ComponentB.jsx
import './ComponentB.css';

function ComponentB() {
  return <button className="button">Button B</button>;
}

After Code (Good)

/* Button.module.css */
.button {
  background-color: blue;
  color: white;
  padding: 10px 20px;
  border: none;
  cursor: pointer;
  font-size: 1em;
}

.primary {
  background-color: red;
}
```
```jsx
// Button.jsx
import styles from './Button.module.css';

function Button({ children, primary }) {
  return (
    <button className={`${styles.button} ${primary ? styles.primary : ''}`}>
      {children}
    </button>
  );
}

// ComponentA.jsx
import Button from './Button';

function ComponentA() {
  return <Button primary>Button A</Button>;
}

// ComponentB.jsx
import Button from './Button';

function ComponentB() {
  return <Button>Button B</Button>;
}