BEM 방법론 소개
게시 됨: 2022-03-11BEM 방법론이란 무엇입니까?
소규모 웹사이트를 구축할 때 스타일을 구성하는 방법은 일반적으로 큰 문제가 아닙니다. 일반적인 파일을 만들고 필요한 모든 CSS를 작성하기만 하면 됩니다. 그러나 더 크고 복잡한 프로젝트의 경우 코드를 구성하는 방법이 중요 합니다. 여러 프론트엔드 및 백엔드 개발자로 구성된 팀에서 작업하는 경우 코드 구조가 훨씬 더 중요합니다.
오늘날 CSS 코드를 줄이고 CSS 코드를 보다 쉽게 유지 관리할 수 있도록 하는 방법론이 많이 있습니다. 이 기사에서는 그 중 하나인 BEM의 몇 가지 예를 설명하고 제공할 것입니다. BEM 은 B 잠금 요소 수정 자를 나타냅니다. 그 배후의 주요 아이디어는 개발 프로세스의 속도를 높이고 CSS 클래스를 독립적인 모듈로 배열하여 개발자의 팀워크를 용이하게 하는 것입니다. header__form--search
와 같은 클래스 이름을 본 적이 있다면 BEM이 작동하는 것입니다. 예, 클래스의 이름은 매우 길 수 있지만 모두 읽기 쉽고 이해할 수 있습니다.
필요한 경우 클래스를 사용하여 이름을 반복하고 보다 일관된 코딩 구조를 생성할 수 있으므로 모범 사례는 ID가 아닌 클래스에만 BEM을 사용하는 것입니다. 또한 웹사이트를 조직화된 모듈로 나누려면 블록, 요소 및 수정자와 같은 동일한 구조로 구성되어야 합니다. 여기서 각 블록은 여러 요소를 가질 수 있으며 블록과 요소는 모두 여러 수정자를 가질 수 있습니다. 하지만 먼저 기본적인 BEM 구조부터 시작하여 예시를 들어 설명하겠습니다.
차단하다
블록은 웹사이트의 개체를 나타냅니다. 코드의 더 큰 구조적 덩어리로 생각하십시오. 오늘날 모든 웹사이트에서 가장 많이 사용되는 블록은 머리글, 콘텐츠, 사이드바, 바닥글 및 검색입니다. BEM의 블록은 항상 CSS 클래스를 연결하는 시작점입니다. 몇 가지 블록 예를 살펴보십시오.
- 내용
- 메뉴
- 검색 양식
.content {/* Styles */} .menu {/* Styles */} .search {/* Styles */}
요소
요소는 특정 기능을 수행하는 블록 내의 구성 요소입니다. 블록의 컨텍스트에서만 의미가 있어야 합니다.
- 콘텐츠 기사
- 메뉴 항목
- 검색 입력 필드
.content__article {/* Styles */} .menu__item {/* Styles */} .search__input {/* Styles */}
수정자
수정자는 블록의 변형을 나타내는 방법입니다. Bootstrap을 사용한 적이 있다면 가장 좋은 예는 버튼 크기입니다. 버튼 크기는 버튼 자체의 크기 변형이므로 수정자가 됩니다.
- 콘텐츠 특집 기사
- 메뉴 링크
- 아이콘이 있거나 없는 검색 필드
.content__article--featured {/* Styles */} .menu__item--link {/* Styles */} .search__input--icon {/* Styles */}
명명 규칙
BEM 방법론의 주요 목적은 CSS 선택자의 이름을 가능한 한 유익하고 투명하게 만드는 것입니다. 원래 BEM 스타일은 다음과 같이 정의됩니다.
블록 이름은 일반적으로 .header
와 같은 단일 단어이지만 더 긴 블록 정의가 있는 경우 단일 하이픈 -
구분됩니다.
.lang-switcher {/* Styles */}
요소 이름은 이중 밑줄 __
로 시작합니다.
.lang-switcher__flag {/* Styles */}
수정자 이름은 단일 밑줄 _
로 시작합니다.
.lang-switcher__flag_basic {/* Styles */}
BEM 방법론에는 단 하나의 매우 중요한 규칙이 있습니다. 수정자는 소유자 컨텍스트 외부에서 사용할 수 없습니다.
예시:
.btn_big {/* Styles */}
헤더도 정의된 경우에만 btn_big
을 사용할 수 있습니다.
나쁜 예:
<div class=”btn_big”>...</div>
좋은 예:
<div class=”btn btn_big”>...</div>
이러한 원래 BEM 스타일 외에도 Harry Roberts 및 CamelCase 스타일과 같은 대체 명명 체계가 있습니다.
해리 로버츠 스타일의 예:
.block-name__element-name--modifier-name {/* Styles */}
CamelCase 스타일의 예:
.BlockName__ElementName_ModifierName {/* Styles */}
다른 것도 거의 없지만 이 두 가지가 가장 일반적인 것입니다. 개인적으로 저는 Harris Roberts가 제안한 명명 규칙의 팬입니다. 이 규칙에는 다음과 같은 규칙이 있습니다.
- 이름은 소문자로 작성
- BEM 엔터티 이름 내의 단어는 하이픈
-
구분됩니다. - 요소 이름은 이중 밑줄
__
로 블록 이름과 구분됩니다. - 부울 수정자는 이중 하이픈으로 구분됩니다.
--
- 키-값 유형 수정자는 사용되지 않습니다.
이 명명 규칙이 다른 것보다 훨씬 잘 구성된 이유는 수정자 요소를 다른 것과 쉽게 구별할 수 있기 때문입니다. 원래 명명 규칙에서 modifier는 다음과 같이 정의됩니다.
.block__element_modifier {/* Styles */}
그러나 보시다시피 단일 밑줄과 이중 밑줄 사이에는 큰 차이가 없습니다. 반면에 이중 하이픈은 명확한 구분을 제공하며 수정자를 즉시 볼 수 있습니다.
.block__element--modifier {/* Styles */}
다양한 형식의 BEM 예
CSS 외에도 BEM은 JSON, XML, 트리 파일 또는 중첩을 지원하는 모든 형식을 구성하는 데 매우 유용합니다. BEM 방법론을 UI를 구축하는 좋은 방법으로 생각하십시오.
BEM 형식으로 구성된 다음 HTML을 살펴보겠습니다.
<header class=”header”> <img class=”header__logo”> <form class=”header__search-from”> <input class=”header__search-from__input” type=”input”> <button class=”header__search-from__button” type=”button”> </form> <div class=”header__lang-switcher”></div> </header>
JSON 및 XML 형식을 사용하여 동일한 결과를 얻을 수 있습니다.
XML:
<block:header> <block:logo/> <block:search-from> <block:input/> <block:button/> </block> <block:lang-switcher/> </block>
JSON:
{ block: 'header', content: [ { block: 'logo' }, { block: 'search-form', content: [ { block: 'input' }, { block: 'button' } ] }, { block: 'lang-switcher' } ] }
BEM 프로젝트의 파일 시스템 구성
BEM에서는 파일을 올바른 방식으로 구성하는 것이 중요합니다. BEM은 CSS 클래스의 훌륭한 구성을 제공하고 완전히 이해할 수 있게 할 뿐만 아니라 유지 관리가 매우 쉬운 파일 구조를 제공합니다. SASS 파일과 함께 BEM 파일 구성 기술을 사용하는 예제 프로젝트를 살펴보겠습니다.
blocks/ input/ __box/ --big/ input__box--big.scss input__box.scss button/ --big/ button--big.scss
위에서 볼 수 있듯이 기본 폴더 내부의 하위 폴더 구조를 보는 것만으로도 모든 것이 명확하고 정리됩니다. 이런 식으로 누가 당신을 따라 일하든, 당신이 누군가를 따라 일하든 차이가 없습니다. 왜냐하면 같은 패턴을 따르는 것이 매우 쉽기 때문입니다.
BEM 프로젝트를 플랫폼으로 나누기
BEM 방법론 기술을 사용하여 파일을 구성하는 것 외에도 더 구체적인 내용으로 이동할 수도 있습니다. 예를 들어, 완전히 반응할 웹 프로젝트를 빌드하고 클라이언트가 모바일의 일부 블록이 데스크톱 장치와 완전히 다르다고 지정한 경우 BEM 폴더 구조를 플랫폼으로 나누는 것이 가장 좋습니다. 다양한 플랫폼에서 버튼을 구성하는 예:
common.blocks/ button/ button.scss desktop.blocks/ button/ buttons.scss mobile.blocks/ button/ button.scss
이것은 BEM 방법론을 사용하여 전체 프로젝트를 구성하려는 경우의 예일 뿐입니다. BEM 구조의 파일 트리는 BEM을 올바르게 사용하기 위해 필수는 아니며 프로젝트의 일부 세그먼트에서만 BEM을 사용할 수 있습니다. 지금까지 나는 모든 요소와 수정자에 파일이 생성되는 엄격한 BEM 파일 구조 구성을 사용하지 않았습니다. 대신 요소와 수정자를 선언한 블록에 대한 파일 구조를 만들고 있습니다.
실제 BEM
이제 명명 규칙에 익숙하므로 실제로 BEM 방법론을 보여 드리겠습니다. 다음 HTML 코드가 실행 중이라고 가정해 보겠습니다.
<a class=”btn btn--big btn--primary-color” href=”#” title=”Title”> <span class=”btn__price”>$3.99</span> <span class=”btn__text”>Product</span> </a>
다음 CSS 마크업이 적용된 경우:
.btn__price {/* Styles */} .btn__text {/* Styles */} .btn--big {/* Styles */} .btn--primary-color {/* Styles */}
이제 오해하지 마십시오. 지금까지의 예제에서 우리는 거의 항상 블록, 요소 및 수정자를 가지고 있었지만 항상 그럴 필요는 없습니다.
예를 들어 person 이라는 블록이 있다고 가정해 보겠습니다. 사람은 다리와 손이 있으며 여성 또는 남성일 수도 있습니다. 오른손으로 남성을 정의하려면 다음과 같습니다.
.person--male__hand--right {/* Styles */}
이제 BEM의 진정한 의미를 알 수 있습니다. 수식어가 성별인 사람을 정의했습니다. 사람이 남자인지 여자인지는 중요하지 않기 때문에 손이 있고 손은 요소입니다. 그리고 다시, 각 사람은 다시 수정자인 오른손 또는 왼손을 가질 수 있습니다.
다른 경우에 일반 사람을 한 손으로 정의하려면 다음과 같이 합니다.
.person__hand {/* Styles */}
보시다시피 BEM에 익숙해지면 CSS와 HTML 구조를 BEM으로 매우 쉽게 구성할 수 있습니다.
CSS 전처리기와 함께 BEM 사용
개인적으로 CSS 전처리기 중 하나를 사용하지 않고 새 프로젝트를 시작하는 것은 상상할 수 없습니다. 알다시피 전처리기는 우리에게 많은 이점을 제공하며 가장 중요한 것은 BEM 방법론과 완벽하게 일치한다는 점입니다.
다음 예에서는 SASS와 결합된 BEM의 가장 일반적인 예를 볼 수 있습니다.
.person { &__hand {/* Styles */} &__leg {/* Styles */} &--male { /* Styles */ &__hand { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } &__leg { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } } &--female { /* Styles */ &__hand { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } &__leg { /* Styles */ &--left {/* Styles */} &--right {/* Styles */} } } }
SASS 코드는 다음 CSS로 컴파일됩니다.

.person__hand {/* Styles */} .person__leg {/* Styles */} .person--male {/* Styles */} .person--male__hand {/* Styles */} .person--male__hand--left {/* Styles */} .person--male__hand--right {/* Styles */} .person--male__leg {/* Styles */} .person--male__leg--left {/* Styles */} .person--male__leg--right {/* Styles */} .person--female {/* Styles */} .person--female__hand {/* Styles */} .person--female__hand--left {/* Styles */} .person--female__hand--right {/* Styles */} .person--female__leg {/* Styles */} .person--female__leg--left {/* Styles */} .person--female__leg--right {/* Styles */}
더 나아가고 싶다면 BEM에 편리한 SASS 믹스인을 사용할 수 있습니다.
/// Block Element /// @param {String} $element - Element's name @mixin element($element) { &__#{$element} { @content; } } /// Block Modifier /// @param {String} $modifier - Modifier's name @mixin modifier($modifier) { &--#{$modifier} { @content; } }
그리고 다음과 같이 사용할 수 있습니다.
.person { @include element('hand') {/* Person hand */} @include element('leg') {/* Person leg */} @include modifier('male') { /* Person male */ @include element('hand') { /* Person male hand */ @include modifier('left') { /* Person male left hand */ } @include modifier('right') { /* Person male right hand */ } } } }
그러면 다음 CSS 출력이 생성됩니다.
.person__hand { /* Person hand */ } .person__leg { /* Person leg */ } .person--male { /* Person male */ } .person--male__hand { /* Person male hand */ } .person--male__hand--left { /* Person male left hand */ } .person--male__hand--right { /* Person male right hand */ }
이렇게 오랫동안 사용 사례가 없을 가능성이 높다는 것을 알고 있지만 이것은 BEM이 사용되는 방법과 소규모 및 대규모 프로젝트 모두에서 BEM이 왜 그렇게 강력한지를 보여주는 좋은 예입니다.
BEM 프로젝트 시작하기
공식 BEM 문서에 설명된 대로 새 BEM 프로젝트를 시작하는 가장 쉬운 방법은 기존 GIT 저장소를 사용하는 것입니다. Git 복제 명령을 사용하기만 하면 됩니다.
$ git clone https://github.com/bem/project-stub.git
다음으로 새로 생성된 디렉터리로 이동하여 모든 종속성을 설치합니다.
$ npm install
필요한 모든 종속성이 설치됩니다.
ENB를 사용하여 프로젝트 빌드:
$ node_modules/.bin/enb make
개발을 위해 서버 모드를 실행합니다.
$ node_modules/.bin/enb server
결과적으로 다음 메시지가 나타납니다.
Server started at 0.0.0.0:8080
이제 이것은 서버가 가동되고 실행 중임을 의미합니다. 이제 이 주소에서 결과를 확인할 수 있습니다.
http://localhost:8080/desktop.bundles/index/index.html
보시다시피 여기에 있는 bemjson
파일 내부에 정의된 많은 요소가 이미 생성되어 있습니다.
project-stub/desktop.bundles/index/index.bemjson.js
localhost index.html
파일에서 볼 수 있는 모든 HTML을 생성하는 파일의 현재 구조를 보고 탐색할 수 있습니다. 우리는 이전 장에서 설명한 "Person" BEM 프로젝트를 얻기 위해 이 파일을 변경할 것입니다. index.bemjson.js
파일에서 전체 코드를 제거(또는 주석 처리)하고 다음 코드로 교체할 수 있습니다.
module.exports = { block: 'page', title: 'Person BEM', favicon : '/favicon.ico', head : [ { elem : 'meta', attrs : { name : 'description', content : '' } }, { elem : 'meta', attrs : { name : 'viewport', content : 'width=device-width, initial-scale=1' } }, { elem : 'css', url : 'index.min.css' } ], scripts: [{ elem : 'js', url : 'index.min.js' }], content: [ { block: 'person', content: [ { elem: 'male', content: [ { elem: 'leg', mods: {side: 'left'}, content: 'Male person leg -- left' }, { elem: 'leg', mods: {side: 'right'}, content: 'Male person leg -- right' }, { elem: 'hand', mods: {side: 'left'}, content: 'Male person hand -- left' }, { elem: 'hand', mods: {side: 'right'}, content: 'Male person hand -- right' } ] }, { elem: 'female', content: [ { elem: 'leg', mods: {side: 'left'}, content: 'Female person leg -- left' }, { elem: 'leg', mods: {side: 'right'}, content: 'Female person leg -- right' }, { elem: 'hand', mods: {side: 'left'}, content: 'Female person hand -- left' }, { elem: 'hand', mods: {side: 'right'}, content: 'Female person hand -- right' } ] }, ] } ] };
이제 다음 HTML이 생성됩니다.
<div class="person"> <div class="person__male"> <div class="person__leg person__leg_side_left"> Male person leg -- left </div> <div class="person__leg person__leg_side_right"> Male person leg -- right </div> <div class="person__hand person__hand_side_left"> Male person hand -- left </div> <div class="person__hand person__hand_side_right"> Male person hand -- right </div> </div> <div class="person__female"> <div class="person__leg person__leg_side_left"> Female person leg -- left </div> <div class="person__leg person__leg_side_right"> Female person leg -- right </div> <div class="person__hand person__hand_side_left"> Female person hand -- left </div> <div class="person__hand person__hand_side_right"> Female person hand -- right </div> </div> </div>
위의 코드에서 볼 수 있듯이 이 시나리오에서는 BEM이 제공한 기본 설정을 사용하고 있기 때문에 기본 BEM 코딩 체계가 사용되었습니다. 새 페이지, 블록 생성 또는 BEM HTML 수정과 같이 탐색하고 사용할 수 있는 훨씬 더 많은 명령과 옵션이 있습니다. 나는 이것에 대해 너무 깊이 들어가지 않을 것이며, 공식 BEM 문서에서 모두 찾을 수 있습니다.
장점 및 우려 사항
장점
- BEM은 유지 관리에 탁월합니다. 대규모 프로젝트에서 누군가를 따라 작업해야 했고 알 수 없는 붕괴 없이 아무것도 변경하는 것이 너무 두려웠습니까? BEM을 사용할 때 요소의 정확한 목적과 요소가 나타날 수 있는 블록을 알 수 있습니다.
- 클래스 이름은 논리적이고 직관적이며 팀의 모든 구성원은 해당 요소가 웹사이트에서 수행하는 작업을 알고 있습니다. BEM은 프로젝트의 모든 사람이 공유할 수 있는 선언적 구문을 제공하므로 동일한 페이지에 있습니다.
- BEM은 중첩된 CSS 선택기를 제거합니다. 모든 단일 HTML 요소에는 고유한 CSS 클래스가 있으며 이름으로 목적이 무엇인지 알 수 있습니다. 그들 모두를 지배하는 하나의 선택자 .
우려 사항 및 일반적인 실수
- 중첩에 너무 깊이 들어가지 마십시오. 주요 규칙은 부모와 자식 수준을 두 개 이상 사용하지 않는 것입니다.
- 블록 범위를 시작하는 위치에 주의하십시오. 여기서 일반적인 실수는 개발자가 블록을 사용하지만 나중에 개발 시점에서 동일한 블록에 중첩으로 규칙을 위반할 수 있는 기본 부모 블록이 있다는 사실을 깨닫지 못하는 것입니다.
- SASS @extend를 피하십시오 . 이에 대해 해리 로버츠의 말을 인용하자면:
Sass에서 클래스를 함께 '연결'하지 않음으로써 보기에서 더 많은 수의 조합을 생성할 수 있습니다. HTML은 DOM의 한 부분에서 작동하는 모든 클래스를 볼 수 있다는 점에서 훨씬 더 나은 페이퍼 트레일을 가지고 있습니다. 새로운 UI를 만들 때마다 새로운 자리 표시자 클래스(또는 이를 결합하는 매니페스트 클래스)를 만들 필요가 없다는 점에서 CSS가 훨씬 더 슬림하게 유지됩니다.
결론
BEM 코딩 방식을 처음 보았을 때 가장 먼저 든 생각은 다음과 같습니다.
이 클래스는 쓰고 읽기에 너무 깁니다.
하지만 사용해보고 나니 이제 사용하지 않고 새 프로젝트를 시작하는 것은 상상할 수 없습니다. 저에게 BEM은 코드 유지 관리성을 크게 향상시켰고, BEM 기반 프로젝트에 "던질" 모든 개발자는 전체 코드 구조를 정말 빨리 따라잡을 것이라고 확신할 수 있습니다.
이 모든 것에도 불구하고 BEM에 대한 소셜 네트워크에 대한 많은 논의가 있습니다. 어떤 사람들은 BEM이 좋지 않다고 말하면서 기본 HTML 중첩 요소를 사용하는 대신 왜 그렇게 긴 이름의 클래스를 작성해야 하는지 의아해합니다. 글쎄요, 아무도 당신이 BEM을 좋아해야 한다고 말하지는 않지만, 사실 대다수의 프론트엔드 개발자들이 BEM을 수용하고 매우 유용하다고 생각합니다.