🎨 Frontend CSS8. 아키텍처 (Tokens·Tailwind·CSS-in-JS)02 — Methodologies (BEM·OOCSS·SMACSS·ITCSS·ECSS)

02 — CSS Methodologies

한 줄 답: 2009~2015년에 등장한 BEM·OOCSS·SMACSS·ITCSS·ECSS는 모두 같은 적과 싸웠다 — CSS 캐스케이드의 전역성. 각자 다른 컨벤션으로 클래스 이름파일 구조를 통제했고, 2022년 이후의 모던 CSS(@layer, @scope)는 언어 수준에서 같은 문제를 해결한다. 메서드론을 알면 왜 Tailwind와 @layer가 등장했는지가 보인다.


Why — 왜 메서드론이 필요했나

2009년경 웹은 50명 개발자 · 수백 페이지 · 한 스타일시트 시대로 진입했다. 문제:

증상원인
.button이 페이지마다 다르게 보임캐스케이드 충돌
한 줄 수정에 회귀 버그 5개전역 스코프
CSS 파일이 5000 줄책임 경계 부재
!important 30개specificity 전쟁
클래스 이름 충돌네임스페이스 부재

해결책은 두 갈래:

  • 언어를 바꾸자 → 표준위원회의 길 (느림: @layer까지 13년 걸림)
  • 컨벤션으로 우회하자 → 메서드론의 길 (빠름: 1~2년이면 사내 적용)

메서드론은 후자다. CSS 자체는 그대로 두고, 우리가 어떻게 쓰는지를 약속한다.


How — 5개 메서드 비교

1) OOCSS (2009, Nicole Sullivan)

아이디어: 객체지향 프로그래밍처럼, 구조(structure)와 스킨(skin)을 분리하라.

<button class="btn btn--primary">Save</button>
/* 구조: 모든 버튼이 공유 */
.btn { padding: 8px 16px; border-radius: 4px; }
/* 스킨: 시각만 */
.btn--primary { background: blue; color: white; }
.btn--danger  { background: red;  color: white; }

원칙 2가지:

  1. 구조와 스킨 분리.
  2. 컨테이너와 콘텐츠 분리 (.sidebar h2보다 .section-title).

유산: 유틸리티 클래스 합성의 사상적 시조. Tailwind의 class="px-4 py-2 rounded bg-blue-500 text-white"는 OOCSS의 극단적 진화.

2) SMACSS (2011, Jonathan Snook)

아이디어: CSS를 5개 카테고리로 분류하라.

카테고리예시접두사
Basebody, a, h1 (요소 기본 스타일)(없음)
Layout.l-grid, .l-sidebarl-
Module.card, .btn(모듈명)
State.is-active, .is-hiddenis- / has-
Theme.theme-darktheme-

유산: 상태 클래스 prefix (is-active)는 React·Vue·Angular의 클래스 토글 패턴으로 살아남았다.

3) BEM (2010~2014, Yandex)

Block · Element · Modifier. 클래스 이름에 구조 정보를 박는다.

<form class="search-form search-form--compact">
  <input class="search-form__input">
  <button class="search-form__submit search-form__submit--disabled">
</form>

문법:

  • Block: search-form (독립 컴포넌트)
  • Element: block__element (블록의 일부)
  • Modifier: block--modifier / block__element--modifier (변형)

원칙:

  • 모든 셀렉터는 클래스 1개 (specificity 0,1,0 고정).
  • 캐스케이드 없음. 자식 셀렉터(>, ) 거의 안 씀.
  • 한 블록은 한 파일.

장점:

  • specificity 균일 → !important 없이 덮어쓰기 가능.
  • 클래스 이름만 봐도 무엇의 어느 부분인지 보인다.
  • 검색 가능성 100% (grep search-form 하면 다 나옴).

단점:

  • 클래스 이름이 길다. card__header__title--featured 같은 게 흔함.
  • HTML이 클래스 폭주.

유산: 가장 광범위하게 채택된 메서드. 2025년에도 디자인 시스템 코어에 흔히 쓰임.

4) ITCSS (2015, Harry Roberts)

Inverted Triangle CSS — specificity를 낮음 → 높음으로 정렬한 7개 레이어.

레이어specificity
Settings0$color-primary: blue;
Tools0@mixin clearfix { ... }
Generic0,0,0,1* { box-sizing: border-box }
Elements0,0,0,1h1 { font-size: 2rem }
Objects0,0,1,0.o-grid { display: grid }
Components0,0,1,0.c-btn { ... }
Utilities0,0,1,0 + !important.u-hide { display: none !important }

유산: @layer의 직접적 모티프. 2022년 W3C가 ITCSS를 언어 기능으로 흡수했다고 볼 수 있음. Tailwind v4의 @layer base, components, utilities도 ITCSS 정확한 압축.

5) ECSS (2015, Ben Frain)

Enduring CSS지속 가능한 CSS를 위해 컴포넌트별 네임스페이스 강제.

<button class="ProductCard-buyButton">Buy</button>

원칙:

  • 모든 클래스에 컴포넌트 prefix (ProductCard-*).
  • 컴포넌트 간 공유 금지 — 차라리 코드 중복.
  • 폐기는 파일 통째로 삭제.

유산: CSS Modules의 해시 스코핑은 ECSS의 자동화다. *“차라리 중복하라”*는 사상은 React 컴포넌트 단위 CSS의 기본 전제.


What — 비교표

메서드핵심specificity 전략파일 구조모던 대응
OOCSS구조·스킨 분리낮게 유지(자유)Utility-first (Tailwind)
SMACSS5 카테고리카테고리별 관리base/layout/module/state/theme컴포넌트 + state 클래스
BEM이름으로 구조 표현0,1,0 균일block 단위CSS Modules + composes
ITCSS역삼각 7층낮음→높음 정렬7층 폴더@layer
ECSS컴포넌트 prefix충돌 방지컴포넌트 단위CSS Modules / styled-components

What — 실전 적용 예: 같은 카드 컴포넌트

BEM

<article class="card card--featured">
  <h2 class="card__title">Title</h2>
  <p  class="card__body">Body</p>
</article>
.card { padding: 16px; }
.card--featured { border: 2px solid gold; }
.card__title { font-size: 1.5rem; }
.card__body { color: gray; }

ITCSS + BEM

/* 1. Settings */
:root { --card-padding: 16px; }
 
/* 2. Objects */
.o-card { padding: var(--card-padding); }
 
/* 3. Components */
.c-card { background: white; border-radius: 8px; }
.c-card--featured { border: 2px solid gold; }
 
/* 4. Utilities */
.u-hidden { display: none !important; }

모던 (@layer)

@layer reset, base, components, utilities;
 
@layer components {
  .card { padding: 16px; background: white; }
  .card[data-featured] { border: 2px solid gold; }
}

같은 결과, 더 적은 코드. @layer가 ITCSS를 언어 기능으로 흡수했기 때문.


What-if — 메서드 선택을 잘못하면

1) BEM을 Tailwind와 섞어 쓴다

<div class="card card--featured px-4 py-2 bg-white">

BEM의 클래스 1개 원칙과 Tailwind의 합성이 충돌. 디자인 토큰이 2군데에 산다. 둘 중 하나만 선택.

2) ITCSS의 7층을 작은 프로젝트에 적용

10개 컴포넌트짜리 앱에 ITCSS는 오버엔지니어링. settings/tools/objects 폴더가 텅 빔. 작은 프로젝트는 컴포넌트 + 글로벌 토큰 2층이면 충분.

3) ECSS의 중복 정책을 무시하고 공유

.ProductCard-title,
.OrderCard-title,
.NotificationCard-title { font-size: 1.5rem; }

ECSS 원칙 위반. 차라리 반복하고, 변경 시 각 컴포넌트가 독립적으로 진화하게 둔다. (단, 디자인 토큰은 공유.)

4) SMACSS의 is- prefix를 데이터 속성으로 교체

{/* SMACSS */}
<div class="modal is-open">
{/* 모던 */}
<div class="modal" data-state="open">

후자가 더 접근성·자동화 친화적. SMACSS의 is- 패턴은 2010년대 jQuery 시대 유산. 모던 React/Vue 코드는 data-* 속성을 권장.


What-if — 모던 CSS가 메서드를 흡수한 양상

ITCSS 레이어모던 CSS 대응
Settings:root { --token: value } + W3C DTCG
ToolsSass/PostCSS 또는 native @mixin (제안 중)
Generic*, *::before, *::after { box-sizing: border-box }
Elements@layer base
Objects@layer components
Components@scope (.card) { ... }
Utilities@layer utilities
/* 모던: ITCSS 7층을 30줄로 압축 */
@layer reset, base, components, utilities;
 
@layer reset { *, *::before, *::after { box-sizing: border-box } }
@layer base  { body { font: 16px/1.5 system-ui } }
@layer components {
  @scope (.card) {
    :scope { padding: 1rem; background: white }
    :scope h2 { font-size: 1.5rem }
  }
}
@layer utilities { .hidden { display: none } }

@scope컴포넌트 격리를, @layerspecificity 정렬을, @property토큰 타입을 — 메서드론이 컨벤션으로 풀던 문제를 언어가 해결한다.


Insight — 컨벤션에서 언어

메서드론은 언어가 늦었다는 사실의 증거다.

1996년 CSS1은 문서 스타일링을 위해 설계됐다. 2009년 우리는 그 언어로 컴포넌트 시스템을 만들려 했다. 언어가 그 일을 잘 못했기 때문에 컨벤션이 등장했다.

  • 2009 OOCSS: “CSS도 객체지향처럼 쓰자”
  • 2011 SMACSS: “카테고리로 나누자”
  • 2014 BEM: “이름에 구조를 박자”
  • 2015 ITCSS: “specificity를 정렬하자”
  • 2015 ECSS: “공유하지 말자”

13년이 지난 2022년, W3C는 CSS Cascade Level 5를 통과시키며 @layer를 도입했다. ITCSS가 컨벤션으로 풀던 specificity 정렬을 언어가 한 줄로 해결한다.

흥미로운 점은 Tailwind가 OOCSS의 극단적 진화라는 것. Nicole Sullivan이 2009년 *“구조와 스킨을 분리하라”*고 했을 때, 그녀는 클래스 합성으로 컴포넌트를 조립할 수 있다는 가능성을 본 것이다. Tailwind는 그것을 극한까지 밀어붙였다 — 모든 클래스가 단 한 가지 속성만 한다.

메서드론은 사라지지 않는다. 언어에 흡수될 뿐이다. BEM의 후예는 CSS Modules의 해시 스코핑이고, ITCSS의 후예는 @layer이며, OOCSS의 후예는 Tailwind다.

언어가 따라잡으면 메서드는 문법이 된다.


요약 + Mermaid

  • OOCSS: 구조·스킨 분리 (→ Tailwind 시조).
  • SMACSS: 5 카테고리 분류 (→ React 상태 클래스 패턴).
  • BEM: block__element--modifier (→ 디자인 시스템 코어에서 여전히 사용).
  • ITCSS: specificity 역삼각 7층 (→ @layer로 흡수).
  • ECSS: 컴포넌트 prefix (→ CSS Modules 해시 스코핑으로 자동화).
  • 모던 CSS(@layer·@scope·@property)는 메서드론의 핵심을 언어가 흡수한 결과.

다음: 03-tailwind — Atomic CSS의 정점, Tailwind v4의 CSS-first 혁명.