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가지:
- 구조와 스킨 분리.
- 컨테이너와 콘텐츠 분리 (
.sidebar h2보다.section-title).
유산: 유틸리티 클래스 합성의 사상적 시조. Tailwind의 class="px-4 py-2 rounded bg-blue-500 text-white"는 OOCSS의 극단적 진화.
2) SMACSS (2011, Jonathan Snook)
아이디어: CSS를 5개 카테고리로 분류하라.
| 카테고리 | 예시 | 접두사 |
|---|---|---|
| Base | body, a, h1 (요소 기본 스타일) | (없음) |
| Layout | .l-grid, .l-sidebar | l- |
| Module | .card, .btn | (모듈명) |
| State | .is-active, .is-hidden | is- / has- |
| Theme | .theme-dark | theme- |
유산: 상태 클래스 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 | 예 |
|---|---|---|
| Settings | 0 | $color-primary: blue; |
| Tools | 0 | @mixin clearfix { ... } |
| Generic | 0,0,0,1 | * { box-sizing: border-box } |
| Elements | 0,0,0,1 | h1 { font-size: 2rem } |
| Objects | 0,0,1,0 | .o-grid { display: grid } |
| Components | 0,0,1,0 | .c-btn { ... } |
| Utilities | 0,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) |
| SMACSS | 5 카테고리 | 카테고리별 관리 | 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 |
| Tools | Sass/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가 컴포넌트 격리를, @layer가 specificity 정렬을, @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 혁명.