
장점:
- 가독성이 뛰어나다.
- 재사용성이 높다.
- 유지보수가 쉽다.
- 검색 엔진 최적화(SEO)에 도움이 된다.
단점:
- 클래스 이름이 길어질 수 있다.
- 다른 클래스 네이밍 규칙과 다르므로 협업 시 일관성 유지가 어렵다.
- 모든 프로젝트에 적용하기에는 지나치게 복잡할 수 있다.
BEM은 무엇인가요?
BEM(Block Element Modifier)은 웹 개발에서 사용되는 CSS 클래스 네이밍 규칙 중 하나입니다. BEM은 모듈식 CSS 아키텍처를 사용하여 CSS 클래스 이름을 구조화합니다. 클래스 이름은 블록, 요소 및 수정자로 구성됩니다.
BEM의 명명규칙
[block]__[element]--[modifier]
블록(Block):
- 페이지 상에서 독립적으로 존재하는 블록의 이름을 나타냅니다.
- 블록 이름은 소문자로 작성하며, 단어 사이에 하이픈(-)을 사용하여 구분합니다.
- 예를 들어, 검색결과 블록의 클래스 이름은 "search-results"가 될 수 있습니다.
요소(Element):
- 블록 내부의 요소를 식별합니다. 요소는 블록 내부에서만 의미가 있으며 블록 간에 공유되지 않습니다.
- 요소의 클래스 이름은 블록의 클래스 이름 뒤에 두 개의 밑줄(__)로 구분하여 작성됩니다.
- 예를 들어, 검색 결과 목록의 각 항목을 나타내는 요소의 클래스 이름은 "search-results__item"이 될 수 있습니다.
수정자(Modifier):
- 블록이나 요소의 상태를 식별합니다. 수정자는 선택적으로 적용됩니다.
- 수정자의 클래스 이름은 블록이나 요소의 클래스 이름 뒤에 두 개의 대시(--)로 구분하여 작성됩니다.
- 예를 들어, 검색 결과 목록의 활성 상태를 나타내는 수정자의 클래스 이름은 "search-results--active"가 될 수 있습니다.
BEM의 장점
- 가독성: BEM은 클래스 이름을 의미있고 명확하게 만듭니다. 클래스 이름만으로도 요소가 어디에 속해 있는지 쉽게 파악할 수 있습니다.
- 재사용성: BEM은 모듈식 CSS를 적용하여 재사용 가능한 코드를 작성하는 데 도움이 됩니다. 블록과 요소를 조합하여 더 큰 블록을 만들 수 있습니다.
- 유지보수성: BEM은 클래스 이름의 구조화로 코드를 이해하고 수정하는 데 도움이 됩니다. 코드를 수정할 때 요소와 수정자의 이름만 변경하면 되므로 다른 부분에 영향을 미치지 않습니다.
BEM은 SEO에도 영향을 미칩니다. 웹 사이트가 검색 엔진에서 쉽게 찾아지는 것은 중요합니다. BEM은 클래스 이름을 구조화하므로 검색 엔진이 콘텐츠를 파악하는 데 도움이 됩니다. 블록은 웹 페이지의 기본 구성 요소를 나타내므로, 검색엔진은 이를 페이지의 주요 콘텐츠로 인식할 수 있습니다. 요소와 수정자는 페이지의 기능을 설명하므로 검색 엔진이 이를 이해하기 쉽습니다. 또한 BEM은 중첩을 피하므로 HTML 구조를 단순화하여 검색 엔진이 콘텐츠를 더 쉽게 파악할 수 있습니다.
BEM의 단점
하지만, BEM을 사용하는 것이 항상 좋은 것은 아닙니다. 클래스 이름이 너무 길어지거나, 중첩된 요소가 많아진다면 코드의 가독성이 떨어질 수 있습니다. 또한, 너무 많은 수식어를 사용하면 CSS 코드가 복잡해질 수 있습니다. 따라서, BEM을 사용할 때에는 적절한 수준에서 클래스를 구조화하고, 필요한 경우에만 수식어를 사용하는 것이 좋습니다.
BEM 코드 예
HTML:
<div class="menu">
<ul class="menu__list">
<li class="menu__item menu__item--active"><a href="#">Home</a></li>
<li class="menu__item"><a href="#">About</a></li>
<li class="menu__item"><a href="#">Contact</a></li>
</ul>
</div>
여기서 "menu"는 블록(block)입니다. "menu__list", "menu__item"은 요소(element)입니다. "menu__item--active"는 수식어(modifier)입니다. 이렇게 명명된 클래스 이름은 코드를 이해하기 쉽고, 스타일을 적용하기 쉽게 만들어 줍니다.
BEM 키워드 연결방법
BEM에서는 기본적으로 kebab-case를 추천합니다. 이는 하이픈으로 연결된 소문자 단어를 사용하는 것을 의미합니다. 예를 들어, .block__element--modifier와 같이 작성됩니다.
- PascalCase: 대문자로 시작하는 단어를 연결하는 방법입니다. 자바스크립트나 C#과 같은 언어에서 클래스명을 작성할 때 주로 사용됩니다. BEM에서는 일반적으로 사용되지 않습니다.
- camelCase: 소문자로 시작하는 단어를 대문자로 연결하는 방법입니다. 자바스크립트에서 변수명을 작성할 때 주로 사용됩니다. BEM에서는 클래스명에 사용할 수 있지만, kebab-case보다 가독성이 떨어질 수 있습니다.
- kebab-case: 하이픈으로 연결된 소문자 단어를 사용하는 방법입니다. BEM에서는 기본적으로 이 방법을 추천합니다. 다른 키워드 연결 방법보다 가독성이 높고, HTML과 CSS에서 모두 사용 가능합니다.
- snake_case: 언더스코어로 연결된 소문자 단어를 사용하는 방법입니다. 일부 언어에서 변수명을 작성할 때 주로 사용됩니다. BEM에서는 일반적으로 사용되지 않습니다.
세계에서는 kebab-case를 포함한 다양한 키워드 연결 방법이 사용됩니다. 하지만 BEM에서는 kebab-case를 추천하고 있으며, 이 방법이 가장 널리 사용되고 있습니다.
고유의 접두어 사용하기
다음의 방법으로도 클래스명을 지정 할 수 있습니다.
예를 들어, "button"이라는 컴포넌트가 있다고 가정해보겠습니다. 이 컴포넌트를 나타내는 클래스 이름은 "button"이 될 수 있습니다. 그러나 만약 이 버튼이 특정한 상황에서만 사용되는 경우, "button"이라는 클래스 이름만으로는 그 용도를 명확히 알 수 없을 수 있습니다. 따라서, 접두어를 추가하여 클래스 이름을 보다 구체적으로 만들 수 있습니다. 예를 들어, "loginButton", "registerButton" 등과 같이 구체적인 접두어를 추가하여 사용할 수 있습니다.
이 방법의 장점은 클래스 이름에서 어떤 컴포넌트를 나타내는지 명확하게 구분할 수 있다는 것입니다. 또한, 같은 기능을 하는 컴포넌트라면, 접두어를 추가하여 일관성 있는 클래스 이름을 사용할 수 있으므로, 재사용성을 높일 수 있습니다.
단점으로는, 클래스 이름이 길어질 수 있다는 것입니다. 또한, 과도한 접두어 사용으로 인해 클래스 이름이 지나치게 복잡해질 수도 있습니다.
BEM에서 타입선택자를 써도 될까?
타입 선택자는 사용하지 않는 것이 원칙입니다. 그 이유는 타입 선택자는 우선순위가 높기 때문에, 스타일 오버라이딩 문제를 야기할 수 있기 때문입니다.
하지만, 예외적인 상황에서는 타입 선택자를 사용할 수도 있습니다. 예를 들어, input 요소나 button 요소와 같은 웹 표준 요소의 경우에는 BEM 방법론을 적용하기 어려울 때가 있습니다. 이 경우에는 BEM 규칙을 따르지 않고, 타입 선택자를 사용해 스타일링할 수도 있습니다.
BEM에서는 타입 선택자를 사용하지 않기 때문에, 대신에 클래스 명을 통해 스타일을 지정합니다. 이를 이용해 예를 들어보면, 다음과 같은 코드를 작성할 수 있습니다.
<!-- HTML -->
<button class="btn btn--primary">Primary Button</button>
<button class="btn btn--secondary">Secondary Button</button>
<style>
/* CSS */
.btn {
border: 1px solid #ccc;
padding: 10px;
}
.btn--primary {
background-color: #007bff;
color: #fff;
}
.btn--secondary {
background-color: #6c757d;
color: #fff;
}
</style>
위의 예시에서, btn 클래스는 모든 버튼 요소에서 공통적으로 사용되는 스타일을 정의합니다. btn--primary 클래스와 btn--secondary 클래스는 각각 주요 버튼과 보조 버튼을 나타내며, 각각의 스타일을 지정합니다. 따라서, 타입 선택자를 사용하지 않고도 BEM 방법론을 이용해 코드를 구성할 수 있습니다.
* 참고: