๐๏ธ 12. CSS ์ํคํ ์ฒ: 'BEM๋ถํฐ CSS-in-JS๊น์ง'
๐ ๊ฐ์
์ปค์ง๋ ํ๋ก์ ํธ ๊ท๋ชจ๋ฅผ ๊ฐ๋นํ ์ ์๊ฒ ํด์ฃผ๋ BEM ๋ช ๋ช ๊ท์น๊ณผ, ํ๋์ ์ธ CSS-in-JS ๋ฐ Utility-first(Tailwind)์ ์ฅ๋จ์ ์ ์์ฒ ์ด์ ํจ๊ป ๋ถ์ํด ๋ด ๋๋ค.
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 11๋ถ(์ ์ฒด) / ํต์ฌ ํํธ๋ง: 6๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
[BEM: ์ด๋ฆ ์ง๊ธฐ์ ๊ท์น] โ [CSS Modules์ CSS-in-JS] โ [Utility-first์ ์ฒ ํ]
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
- BEM ํจํด์ ํ์ฉํด ๋๊ตฌ๋ ์ดํดํ ์ ์๋ ํด๋์ค ์ด๋ฆ์ ์ง์ต๋๋ค.
- ๊ธ๋ก๋ฒ ๋ค์์คํ์ด์ค ์ค์ผ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ค์ํ ํ๋์ ๊ธฐ๋ฒ์ ์ตํ๋๋ค.
- ํ๋ก์ ํธ์ ์ฑ๊ฒฉ์ ๋ง์ถฐ ์ ์ ํ CSS ๋ฐฉ๋ฒ๋ก (Module vs Styled vs Tailwind)์ ์ ํํฉ๋๋ค.
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ๐ฃ ์์ฒ ( ์ ์
): "์ํธ ๋! ์ ๊ฐ ๊ณต๋ค์ฌ ๋ง๋
.title์คํ์ผ์ด ๋ค๋ฅธ ํ์ด์ง์์ ๋ง๋ ๋๊ฐ์ ์ด๋ฆ์.title๋๋ฌธ์ ๋ค ๊นจ์ก์ด์. ํด๋์ค ์ด๋ฆ์very-special-title-blue-03์ด๋ ๊ฒ ์ง์ด์ผ ํ๋์? ๐ญ" - ๐ฆ ์ํธ ( ๋ฆฌ๋ ): "์์ฒ ๋, ๊ทธ๊ฒ ๋ฐ๋ก CSS์ ๊ฐ์ฅ ํฐ ์์ ์ธ 'Global Scope' ๋ฌธ์ ์ ๋๋ค. ์ ์ธ๊ณ ๊ฐ๋ฐ์๋ค์ด ์ด ํผ๋์ ๋ง์ผ๋ ค๊ณ ์๋ง์ ๊ท์น(Architecture)์ ๋ง๋ค์์ฃ . ์ค๋ ๊ทธ ํํ์ ๋๊ตฌ๋ค์ ํ๋์ฉ ๊บผ๋ด๋ณด๊ฒ ์ต๋๋ค."
๐ค ์ ์์์ผ ํ๋๊ฐ
CSS์ ๊ฐ์ฅ ํฐ ์ฝ์ ์ ๋ชจ๋ ์คํ์ผ์ด ์ ์ญ(Global)์ ๋ฐ์๋๋ค๋ ๊ฒ์ ๋๋ค. ํ๋ก์ ํธ๊ฐ ์ปค์ง๊ณ ํผ์์ ๋ง ๊ฐ ์ด์์ ํด๋์ค๋ฅผ ๊ด๋ฆฌํ๊ฒ ๋๋ฉด, ์คํ์ผ ํ ์ค ๊ณ ์น๋ ๊ฒ ์ง๋ขฐ๋ฐญ์ ๊ฑท๋ ๊ฒ์ฒ๋ผ ๋ฌด์์์ง๋๋ค.
5๋ ์ฐจ ์ด์์ ์๋์ด๋ ๋จ์ํ ์ฝ๋๊ฐ ์์ ๊ฑธ ๋์ด, **'์์ธก ๊ฐ๋ฅํ ์ฝ๋'**๋ฅผ ์งญ๋๋ค. ๋ด๊ฐ ๊ณ ์น ํด๋์ค๊ฐ ๋ค๋ฅธ ํ์ด์ง์ ๋ฒํผ์ ๋ง๊ฐ๋จ๋ฆฌ์ง ์์ ๊ฑฐ๋ผ๋ ํ์ ! ๊ทธ ํ์ ์ ์ฃผ๋ ๊ฒ์ด ๋ฐ๋ก ์ํคํ ์ฒ์ ๋๋ค.
๐ท๏ธ 1. BEM: ํด๋์ค์ ๊ณ๊ธ์ ๋ถ์ฌํ๋ผ
Block, Element, Modifier์ ์ฝ์๋ก, ๊ฐ์ฅ ์ ์ ๊น๊ณ ๊ฐ๋ ฅํ ๋ช ๋ช ๊ท์น์ ๋๋ค.
/* ๐ฆ ์ํธ: ํด๋์ค ์ด๋ฆ๋ง ๋ด๋ HTML ๊ตฌ์กฐ๊ฐ ๊ทธ๋ ค์ ธ์ผ ํฉ๋๋ค. */
.card {} /* Block: ๋
๋ฆฝ์ ์ธ ์ปดํฌ๋ํธ */
.card__title {} /* Element: ์กฐ๊ฐ (__ ์ฌ์ฉ) */
.card__button--disabled {} /* Modifier: ์ํ๋ ๋ณํ (-- ์ฌ์ฉ) */๐ฃ ์์ฒ : "์, ์ด๋ฆ์ ์ข ๊ธธ์ด์ง์ง๋ง ์ค๋ณต๋ ์ผ์ ์ ๋ ์๊ฒ ๋ค์! ๊ทธ๋ฆฌ๊ณ ์ฃผ์์ด ์์ด๋ ์ด๋์ ์ฐ์ด๋ ๊ฑด์ง ๋ฐ๋ก ์๊ฒ ์ด์."
๐ก๏ธ 2. ์ค์ฝํ ๊ฒฉ๋ฆฌ: CSS Modules & CSS-in-JS
๋ธ๋ผ์ฐ์ ๊ฐ ์๋ ๋น๋ ๋๊ตฌ์ ํ์ ๋น๋ ค ํด๋์ค ์ด๋ฆ์ ๊ณ ์ ํ๊ฒ(Hash) ๋ฐ๊พธ๋ ๋ฐฉ์์ ๋๋ค.
- CSS Modules:
.title์ด ๋น๋ ์.title_a8x2๋ก ๋ณํด ๋ค๋ฅธ ํ์ผ๊ณผ ์ถฉ๋ํ์ง ์์ต๋๋ค. - CSS-in-JS (Styled-components, Emotion): ์๋ฐ์คํฌ๋ฆฝํธ ๋ณ์ ์์ CSS๋ฅผ ๊ฐ๋ก๋๋ค. "CSS๋ ์ปดํฌ๋ํธ์ ์ผ๋ถ๋ค"๋ผ๋ ์ฒ ํ์ ๋๋ค.
๐ฆ ์ํธ์ ์กฐ์ธ:
"์ต๊ทผ์๋ ๋ฐํ์ ์ค๋ฒํค๋ ๋๋ฌธ์ Zero-runtime CSS-in-JS (Vanilla Extract ๋ฑ)๋ Tailwind CSS๋ก ํ๋ฆ์ด ๋์ด๊ฐ๊ณ ์์ฃ . ๋๊ตฌ๋ ๋ณํ์ง๋ง '๊ฒฉ๋ฆฌ'์ '์ ์ง๋ณด์'๋ผ๋ ๋ณธ์ง์ ๊ฐ์ต๋๋ค."
โก 3. Utility-first: Tailwind์ ํ๋ช
ํด๋์ค๋ฅผ ์๋ก ์ง์ง ๋ง๊ณ , ๋ฏธ๋ฆฌ ๋ง๋ค์ด์ง ์์ฑ๋ค(flex, p-4, text-blue-500)์ ์กฐ๋ฆฝํ๋ ๋ฐฉ์์
๋๋ค.
- ์ฅ์ : ์ด๋ฆ ์ง๋ ๊ณ ํต์์ ํด๋ฐฉ๋ฉ๋๋ค. ๋น ๋ฅธ ํ๋กํ ํ์ดํ์ด ๊ฐ๋ฅํฉ๋๋ค.
- ๋จ์ : HTML์ด ์ง์ ๋ถํด ๋ณด์ผ ์ ์๊ณ , ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์กด์ฑ์ด ์๊น๋๋ค.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. BEM ๋ฐฉ์์์ ์์(Element)๋ฅผ ๋ํ๋ด๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ธฐํธ๋ ๋ฌด์์ธ๊ฐ์?
โ
์ ๋ต: __ (์ด์ค ์ธ๋๋ฐ)
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ: BEM์
Block__Element--Modifier๊ตฌ์กฐ๋ฅผ ๋ฐ๋ฆ ๋๋ค. ๋ธ๋ก ๋ด๋ถ์ ๊ตฌ์ฑ ์์์์ ๋ํ๋ผ ๋๋__๋ฅผ ์ฌ์ฉํฉ๋๋ค. - ์ค๋ต ํผ๋๋ฐฑ: "์์ฒ ๋, ํ์ดํ(-) ํ๋๋ ์ผ๋ฐ์ ์ธ ๋จ์ด ์ฐ๊ฒฐ์ด๊ณ , ํ์ดํ ๋ ๊ฐ(--)๋ ์ํ ๋ณํ(Modifier)๋ฅผ ๋ปํด์. ํท๊ฐ๋ฆฌ์ง ๋ง์ธ์!"
Q2. CSS Modules๋ฅผ ์ฌ์ฉํ ๋ ์ป์ ์ ์๋ ๊ฐ์ฅ ํฐ ๊ธฐ์ ์ ์ด๋์ ๋ฌด์์ธ๊ฐ์?
- CSS ํ์ผ ์ฉ๋์ด ์ค์ด๋ ๋ค.
- ์ ๋๋ฉ์ด์ ๊ตฌํ์ด ์ฌ์์ง๋ค.
- ํด๋์ค ์ด๋ฆ์ด ์ ์ญ์์ ์ถฉ๋ํ๋ ๊ฒ์ ์๋์ผ๋ก ๋ฐฉ์งํ๋ค.
- ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์ ํ์ ํธํ์ฑ์ ๋ณด์ฅํ๋ค.
โ
์ ๋ต: 3. ํด๋์ค ์ด๋ฆ์ด ์ ์ญ์์ ์ถฉ๋ํ๋ ๊ฒ์ ์๋์ผ๋ก ๋ฐฉ์งํ๋ค.
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ: CSS Modules๋ ๋น๋ ํ์์ ํด๋์ค ์ด๋ฆ ๋ค์ ๊ณ ์ ํ ํด์๊ฐ์ ๋ถ์ฌ์ค๋๋ค. ๋๋ถ์ ์ฌ๋ฌ ํ์ผ์์ ๊ฐ์ ์ด๋ฆ์ ์จ๋ ์๋ก ๊ฐ์ญํ์ง ์๋ ๋ ๋ฆฝ์ ์ธ '์ค์ฝํ'๊ฐ ํ์ฑ๋ฉ๋๋ค.
- ์ค๋ต ํผ๋๋ฐฑ: "์์ฒ ๋, ์ด์ ๋ ์ด์
.title-final-final-v2๊ฐ์ ์ด๋ฆ์ ์ง์ ํ์๊ฐ ์๋ค๋ ๋ป์ด์์. ํด์์ ํ์ ๋ฏฟ์ผ์ธ์!"
Q3. [์์ฒ ์ด์ ํ
์คํธ ํ์: ์ค๋ฌด ๋๋ ๋ง]
์์ ๋์ด "์ฐ๋ฆฌ ํ๋ก์ ํธ๊ฐ ์ ์ ์ปค์ง๊ณ ์๋๋ฐ, SASS์ ์ค์ฒฉ(Nesting) ๊ธฐ๋ฅ์ ์จ์ ์ ํ์๋ฅผ ๋๋ฌด ๊น๊ฒ(์: .header nav ul li a) ์ง๋์์ ์์ ์ด ๋๋ฌด ํ๋ค๋์"๋ผ๊ณ ํ์ญ๋๋ค. ์ํธ ๋ฆฌ๋ ๋์ด ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด "์ ํ์์ ๊น์ด๋ฅผ 1๋จ๊ณ๋ก ์ ์งํ์"๊ณ ๊ถํ์
จ์ต๋๋ค. ์์ฒ ์ด๊ฐ ์ด๋ฅผ ์ํด ๋์
ํด์ผ ํ ๋ช
๋ช
๊ท์น์?
โ
์ ๋ต: BEM (Block Element Modifier)
๐ก ์์ธ ํด์ค:
- ์๋ฆฌ ์ค๋ช
: BEM์
.block__element์ฒ๋ผ ๋จ์ผ ํด๋์ค์ ๋ชจ๋ ๊ณ์ธต ์ ๋ณด๋ฅผ ๋ด์ต๋๋ค. ๋ฐ๋ผ์ CSS๋ฅผ ์งค ๋ ์์ ์ ํ์(>)๋ ์ค์ฒฉ์ ๊น๊ฒ ์ธ ํ์๊ฐ ์์ด ๋ช ์๋ ๊ด๋ฆฌ์ ์ฑ๋ฅ ๋ฉด์์ ์๋ฑํฉ๋๋ค. - ์ค๋ต ํผ๋๋ฐฑ: "์์ฒ ๋, ์ค์ฒฉ์ ๋ง์ด ์ฐ๋ ๊ฑด ๋์ค์ ๊ทธ ์ฝ๋๋ฅผ ๋ค์ ๋ณด๊ณ ์ถ์ง ์๊ฒ ๋ง๋๋ ์ง๋ฆ๊ธธ์ ๋๋ค. BEM์ผ๋ก ํ๋ฉด์ ์ธ ๊ตฌ์กฐ๋ฅผ ๋ง๋์ธ์."
- ๐ ํต์ฌ ๊ธฐ์ต๋ฒ: "ํด๋์ค ์ด๋ฆ์ ๊ธธ๊ฒ, ์ ํ์ ๊น์ด๋ ์๊ฒ!"
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋์ ๋ด ํด๋์ค ์ด๋ฆ๋ค์ด ์ ๊ทธ๋ ๊ฒ ์๋ง์ด์๋์ง ๊นจ๋ฌ์๋ค.
.title1, .title_final, .title_real_final... ์ด๋ฐ ์ด๋ฆ๋ค๋ก ํ๋ก์ ํธ๋ฅผ ์ฑ์ ๋ ๊ณผ๊ฑฐ์ ๋ด๊ฐ ๋ถ๋๋ฌ์์ก๋ค.
BEM์ ์ฒ์ ๋ดค์ ๋๋ __๋ --๊ฐ ์ง์ ๋ถํด ๋ณด์๋๋ฐ, ๋ง์ ์จ๋ณด๋ ์ด๋ณด๋ค ๋
ผ๋ฆฌ์ ์ธ ๊ฒ ์๋ค.
๐ก "์ํคํ ์ฒ๋ ์ ์ฝ์ด ์๋๋ผ ์์ ๋ค. ๊ท์น์ ๋ฐ๋ฅผ ๋ ๋น๋ก์ ๊ฑฐ๋ํ ์ฝ๋์ ๋ฐ๋ค์์ ๊ธธ์ ์์ง ์์ ์์ ๋ฅผ ์ป๋๋ค."
์ํธ ๋์ด "๋๊ตฌ๋ ์ ํ์ ํ์ง๋ง, ์ํคํ
์ฒ์ ์ฌ๊ณ ๋ ํ์ ๊ฐ๋ค"๋ผ๊ณ ํ์ ๋ง์ด ๊ธฐ์ต์ ๋จ๋๋ค.
Tailwind๋ฅผ ์ฐ๋ Styled-components๋ฅผ ์ฐ๋ , ๊ฒฐ๊ตญ '๊ด์ฌ์ฌ๋ฅผ ์ด๋ป๊ฒ ๋ถ๋ฆฌํ ๊ฒ์ธ๊ฐ'๊ฐ ํต์ฌ์ด๋ผ๋ ๊ฑฐ์ง.
์ง์ ๊ฐ์ ๋ด ์๋ง์ง์ฐฝ์ธ ๊ฐ์ธ ํ๋ก์ ํธ ํด๋์ค ์ด๋ฆ๋ค๋ถํฐ ํ๋์ฉ BEM์ผ๋ก ์์ ํด์ค์ผ๊ฒ ๋ค. ์ค๋๋ ์ฑ์ฅ ์๋ฃ! ๐๏ธ