기본 구조
block__element--modifier
| 구성 | 설명 | 예시 |
|---|
| Block | 독립적인 컴포넌트 단위 | .card, .nav, .button |
| Element | Block의 구성 요소 (__ 구분) | .card__title, .nav__item |
| Modifier | 상태/변형 (-- 구분) | .button--primary, .card--featured |
기본 예시
<div class="card card--featured">
<img class="card__image" src="..." />
<h2 class="card__title">제목</h2>
<p class="card__description card__description--truncated">내용</p>
<button class="card__button button button--primary">더보기</button>
</div>
.card { }
.card__image { }
.card__title { }
.card--featured { }
.card__description--truncated { }
핵심 규칙
- Block은 독립적 — 어디서든 재사용 가능해야 함
- Element는 Block 외부에서 단독 사용 불가 —
.card__title은 .card 안에서만 의미 있음
- Modifier는 단독으로 사용하지 않음 —
.button--primary만 쓰지 말고 .button.button--primary로 사용
- 중첩 Element 금지 —
.card__body__title (X) → .card__title (O)
하이픈과 언더바 혼합 사용
BEM에서 -와 __, --는 역할이 명확히 분리됨.
| 역할 | 구분자 | 예시 |
|---|
| Block 내 단어 연결 | - | search-form |
| Element 구분 | __ | search-form__input |
| Element 내 단어 연결 | - | __submit-button |
| Modifier 구분 | -- | --full-width |
| Modifier 내 단어 연결 | - | --dark-theme |
<form class="search-form search-form--inline">
<input class="search-form__text-input" />
<button class="search-form__submit-button search-form__submit-button--full-width">
검색
</button>
</form>
현장 사용 패턴
1. 순수 BEM (레거시 / 순수 CSS 프로젝트)
.c-card { }
.c-card__header { }
.c-card__title { }
.c-card--featured { }
c- 같은 네임스페이스 prefix를 붙이는 패턴도 흔함 (ITCSS 영향)
- 대형 기업 디자인 시스템, 레거시 프로젝트에서 여전히 사용
2. CSS Modules + 약식 BEM (React 현장 주류)
.root { }
.header { }
.title { }
.featured { }
<div className={`${styles.root} ${featured && styles.featured}`}>
<h2 className={styles.title}>...</h2>
</div>
__, -- 구분자를 생략하고 파일 단위 캡슐화로 충돌 방지
- React 환경에서 가장 많이 보이는 절충안
3. Tailwind + 컴포넌트 분리 (최근 트렌드)
const Card = ({ featured }: Props) => (
<div className={cn('rounded-lg p-4', featured && 'border-2 border-blue-500')}>
<h2 className="text-xl font-bold">...</h2>
</div>
)
- 컴포넌트 자체가 Block 역할을 대체
- 네이밍 충돌 문제가 구조적으로 사라짐
환경별 채택 현황
| 환경 | 주로 쓰는 방식 |
|---|
| 레거시 멀티페이지 | 순수 BEM |
| React + CSS Modules | 약식 BEM (구분자 생략) |
| React + Tailwind | BEM 거의 안 씀 |
| 디자인 시스템 (MUI, Ant 등) | 내부적으로 BEM 유지 |
Tailwind 시대의 BEM 위상
Tailwind가 BEM을 대체한 부분
| 문제 | BEM 해결 방식 | Tailwind 해결 방식 |
|---|
| 클래스 충돌 | 긴 네이밍으로 격리 | 유틸리티 클래스 = 충돌 없음 |
| 상태 표현 | --modifier | hover:, disabled: 등 |
| 재사용 | 클래스 조합 | 컴포넌트 추상화 |
BEM이 여전히 의미 있는 곳
- 디자인 시스템 / 라이브러리 개발 — 외부 배포 CSS는 소비자 환경을 모르므로 BEM으로 충돌 방지 필요
- Tailwind 없는 환경 — 레거시 유지보수, 백오피스, 순수 HTML/CSS 프로젝트
- 사고 방식으로서의 가치 — Block/Element/Modifier로 분류하는 멘탈 모델은 컴포넌트 설계 단계에서 유효
결론
BEM을 문법으로 외울 필요는 없지만, 개념은 알고 있어야 함.
- 신규 프로젝트 → Tailwind + 컴포넌트 분리로 충분, BEM 우선순위 낮음
- 레거시 코드 읽기 → BEM 모르면 해독이 어려움
- 라이브러리 / 디자인 시스템 개발 → BEM이 여전히 표준에 가까움
- 설계 관점 → Block/Element/Modifier 사고방식은 Tailwind 환경에서도 유효한 멘탈 모델