세상이 바뀌는 속도보다 약간 더 빠르게 웹은 발전하고 있습니다.
특히 그 중에서도 CSS는 기존에 경험하지 못한 속도로 다양한 부분이 변화하고 있습니다.
CSS의 활용도가 높아지고 대규모 프로젝트가 많아짐에 따라,
복잡한 설계의 필요성을 느끼지 못했던 CSS에도 다양한 방법론들이 생기기 시작했습니다.
CSS 방법론의 필요성을 사내에서도 느끼고 있었고,
같은 필요성을 느끼고 있던 다른 팀원들과 함께 CSS방법론(SMACSS, BEM, OOCSS)에 대해서 스터디를 하였습니다.
방법론의 특징에 따라서 장단점이 있었으나,
세 방법론 모두 같은 지향점을 갖고 있었습니다.

  • 코드의 재사용성을 높이자
  • 쉽게 유지보수 하자
  • 확장 가능하게 하자
  • 클래스명 만으로도 무슨 의미인지 예측 가능하도록 하자

대부분의 언어에서도 비슷한 지향점을 가지고 있을 거라 추측합니다.
세가지 방법론을 각각 자세히 알아보도록 하겠습니다.

smacss logo
SMACSS
(Scalable and Modular Architecture for CSS)

정의

  • CSS에 대한 확장형 모듈식 구조(by Jonathan Snook)
  • CSS의 프레임워크가 아닌 하나의 스타일 가이드

사용목적

  • Class명을 통한 예측
  • 재 사용
  • 쉬운 유지보수
  • 확장 가능

핵심 규칙 분류

  1. Base
    • 기본 스타일(Reset, Default, Variables, Mixins)
    • 기본 스타일에는 !important를 쓸 필요가 없다.
      body,p,h1,h2,h3,h4,h5,h6,ul,ol,li,dl,dt,dd,table,th,td,form,fieldset,legend,input,
      textarea,button,select{margin:0;padding:0}
      body,input,textarea,select,button,table{font-size:14px;line-height:1.25}
      body.s,.s input,.s textarea,.s select,.s button,.s table{font-family:helvetica}
      body{position:relative;background-color:#fff;color:#000}
      body.s{-ms-text-size-adjust:none;-webkit-text-size-adjust:none}
      img,fieldset{border:0}
      ul,ol{list-style:none}
      table{border-collapse:collapse}
      em,address{font-style:normal}
      a{color:inherit;text-decoration:none}

      파일 구조

  2. Layout
    • 레이아웃과 관련된 스타일 정의
    • Class명에 suffix “l-”를 붙인다
      #content {
        width: 80%;
        float: left;
      }
      #aside {
        width: 20%
      }
      
      .l-fixed #content {
        width: 600px;
        margin-right: 10px;
      }
      .l-fixed #aside {
        width: 200px
      }
      
  3. Module(Components)
    • 모듈 관련 스타일
    • 스타일 재 사용을 위한 요소
    • Block, Element, Module
    • 재사용을 위해 id 셀렉터와 element를 사용하지 않는다.
      만약, element 셀렉터를 사용해야 한다면, .box > span 처럼 child 셀렉터를 사용
    • 사용 예시) nav bar, 이미지 슬라이더, dialogs, widgets, tables, icons
      <div class="forder">
      	<span>Forder Name</span>
      </div>
      <div class="box">
      ...
      </div>
      <div class="basket">
      ...
      </div>
      .folder >span {
        padding-left: 20px;
        background: url(icon.png);
      }
      
  4. State
    • 상태를 나타내는 스타일
    • Hidden, expend, active, hover 등의 상태에서 사용
    • Class명에 suffix “is-” 또는 “s-”를 붙여서 사용
      <div class="btn_area">
        <a href="#" class="btn btn_good is-active">좋아요버튼</a>
        <a href="#" class="btn btn_bad">나빠요버튼</a>
      </div>
      
      .btn {
        display: inline-block;
        background:#ddd;
        border-radius:4px;
      }
      .btn.is-active{
        background:#43f837;
      }
      .btn.is-hidden {
        display: none;
      }
      
  5. Theme
    • 사이트 전반적 look and feel 제어
    • 색상이나 이미지를 불변하는 스타일과 분리, 기존 스타일을 재 선언하여 사용할 수 있다.
    • 적용범위가 넓은 테마는 “theme-”를 suffix를 붙여 사용한다.
      .mod {
      	border: 1px solid;
      }
      
      .mod {
      	border-color:blue
      }
      

SMACSS의유의사항

  • 파생된 CSS 셀렉터 사용금지
  • ID 셀렉터 사용금지
  • !important 사용 금지
  • Class 이름은 의미있게, 다른 개발자가 이해할 수 있도록 선언

참고 사이트

http://www.slideshare.net/fitc_slideshare/presentation-scalable-and-modular-css-fitcam
http://www.slideshare.net/maxdesign/css-oocss-and-smacss

BEM logo
BEM
(Block, Element, Module)

정의

  • BEM은 Block Element Modifier의 약자이다
  • OOP(Object Oriented Programming)와 유사하다
  • ID는 사용할 수 없고, 오직 class명만 사용할 수 있다
  • .header__navigation‐‐secondary과 같은 class를 사용한다

Block

  • block은 문단 전체에 적용된 element 또는 element를 담고 있는 컨테이너를 말한다.
    ex) logo / login form / menu / search from / content / footer

    <div class="header">
      <div class="menu">....</div>
      <div class="search">....</div>
    </div>
    

    BEM_2
    BEM_3

Element

  • element는 block 안에서 특정 기능을 수행하는 컴포넌트이다. element는 상황에 따라 달라진다.
    각 element는 두 개의 밑줄표시로 연결하여 block 다음에 작성한다.

    .header__logo { … }
    .header__menu { … }
    .header__search { … }
    .header__login { … }
    
  • block 이름이나 element 이름이 길 경우 – 하이픈으로 연결한다. (강제성은 없음, 프로젝트의 규칙을 적용하면 됨)
    .block-name__element-name
    

    BEM_4

Modifiers

  • Modifier은 block 또는 element의 속성이다
  • 이 속성은 block 또는 element의 외관이나 상태를 변화시킨다
  • Class명은 “–“를 추가하여 modifier 추가
    .block‐‐modifier {…}
    .block__element--modifier {…}
    
  • 탭 메뉴가 다른 영역에서 다른 스타일로 사용된다면,
    • 메인 속성을 복사하여 추가 하거나,
    • 전 처리 장치인 sass의 @extend를 활용하여 속성을 상속 받을 수 있다
    .header__navigation {
          background: #008cba;
          padding: 1px 0;
          margin: 2px 0;
    }
    .header__navigation‐‐secondary {
          @extend .header__navigation;
          background: #dfe0e0;
     }
    
  • class명이 길다?
    • BEM의 class명은 구체적이고 명료하여 HTML안에서도 읽기 쉬워야 한다
    • class명이 무엇을 나타내는지 분명하게 전달돼야 한다

 

그외+

 

참고 사이트

https://en.bem.info/
http://www.smashingmagazine.com/2012/04/16/a-new-front-end-methodology-bem/

OOCSS
(Object Oriented CSS)

정의

  • Object Oriented CSS의 약자
  • Nicole Sullivan에 의해 개발된 프레임워크
  • CSS를 모듈 방식으로 코딩하여 중복을 최소화하는 기법

주요원리

  • 구조와 외양을 분리하자.
    외양(skin)으로 분리시켜, 결합시키면 다양한 결과물을 얻을 수 있음.

    .button {
       ...
    }
    .box {
       ...
    }
    .widget {
       ...
    }
    .skin {
       background: linear-gradient(#ccc, #222);
       box-shadow: rgba(0, 0, 0, .5) 2px 2px 5px;
    }
    
  • 컨테이너와 컨텐츠를 분리하자.
    .header-inside{
       position:relative;
       margin:0 auto;
       width:980px;
       height:260px;
       padding:20px;
       overflow:hidden;
    }
    

    다른 영역에서도 사용가능하도록 .header-inside라는 속성으로 추출(분리)하면,
    중복 코드를 사용하게 되는 경우가 적어진다.

    .globalwidth{
       position:relative;
       padding-left:20px;
       padding-right:20px;
       margin:0 auto;
       width:980px;
       overflow:hidden;
    }
    .header-inside{
       padding-top:20px;
       padding-bottom:20px;
       height:260px;
    }
    
    <div class="header-inside globalwidth"></div>
    <div class="main globalwidth"></div>
    <div class="footer-inside globalwidth"></div>
    

클래스 이름 짓기

  • 간결함: 되도록 짧게
  • 명료함: 스타일과 작동 방식이 고스란히 드러나게
  • 분명한 말뜻(Semantics): 어떻게 생겼는지가 아니라, 어떤 모듈인지
  • 포괄성: 대부분의 사이트에서도 적용되도록
  • 화면 중심성: 종이나 다른 매체가 아닌 모니터를 기준으로
  • Example
    • HTML 코드를 시멘틱하게 짜고자 할때, 아래와 같이 CSS를 작성하는 경우가 많다.
      .twitterbtn {
        border:3px solid #000;
        padding:10px 20px;
        color:#fff;
        border-radius:10px;
        background:red;
      }
      .facebookbtn {
        border:3px solid #000;
        padding:10px 20px;
        color:#fff;
        border-radius:10px;
        background:gray;
      }
      
      <a href="#" class="twitterbtn">Twitter</div>
      <a href="#" class="facebookbtn">Facebook</div>
      

      중복되는 스타일이 많다..

    • 여기서! OOCSS를 적용하게 되면,
      .btnbase {
        border:3px solid #000;
        padding:10px 20px;
        color:#fff;
        border-radius:10px;
      }
      .twitter {
        background:red;
      }
      .facebook {
        background:gray;
      }
      
      <a href="#" class="btnbase twitter">Twitter</div>
      <a href="#" class="btnbase facebook">Facebook</div>
      

      CSS코드는 간결해지지만, HTML 코드는 살짝 복잡해지는 경우가 많다.
      이러한 경우가 OOCSS의 한계..? 라고 할 수 있다.
      방법이 아예 없는 것은 아니다.
      [아래 참고]

장/단점 – [참고]OOSass

    • OOCSS의 장점
      • 코드의 재사용성
      • 코드 재사용으로 인한 스타일시트의 용량 축소
      • 스타일시트의 용량 축소로 인한 속도 향상

 

  • OOCSS의 단점
    • 다중 클래스 사용으로 HTML가 복잡해짐
    • non-semantic한 클래스 사용
    • Sass와 함께 사용하게 되면 단점을 보완할 수 있음
      [참고] OOCSS + Sass = OOSass (http://mytory.net/archives/8986/)CSS에서 OOCSS를 적용하는 것이 아니라,
      pre-css layer에서 OOCSS를 적용하여 class를 확장하는 방법.

      OOCSSSass의 mixin, extend 방식을 사용하면 Semantic한 HTML코드를 얻을 수 있다. (두 방법의 HTML코드는 동일함)

      @mixin btnbase{
        border:3px solid #000;
        padding:10px 20px;
        color:#fff;
        border-radius:10px;
      }
      .twitterbtn {
        @include btnbase;
        background:red;
      }
      .facebookbtn {
        @include btnbase;
        background:gray;
      }
      
      .btnbase{
        border:3px solid #000;
        padding:10px 20px;
        color:#fff;
        border-radius:10px;
      }
      .twitterbtn {
        @extend .btnbase;
        background:red;
      }
      .facebookbtn {
        @extend .btnbase;
        background:gray;
      }
      

      OOCSS_2

      <a href="#" class="twitterbtn">Twitter</div>
      <a href="#" class="facebookbtn">Facebook</div>
      

      하지만, 두 방법은 Compile시에는 차이가 있다.

      .twitterbtn {
        border: 3px solid #000;
        padding: 10px 20px;
        color: #fff;
        border-radius: 10px;
        background: red; }
      .facebookbtn {
        border: 3px solid #000;
        padding: 10px 20px;
        color: #fff;
        border-radius: 10px;
        background: gray; }
      
      .btnbase,.twitterbtn,.facebookbtn {
        border: 3px solid #000;
        padding: 10px 20px;
        color: #fff;
        border-radius: 10px; }
      .twitterbtn {
        background: red; }
      .facebookbtn {
        background: gray; }
      

      mixin방식으로 했을 경우는 중복된 코드가 발생하므로,
      extend방식으로 하는 것이 더 좋다.

 

좋은습관/나쁜습관

  • 좋은 습관
    • Component Library를 이용하여 HTML을 구성하자. (like lego)
      http://pflannery.github.io/oocss-skeleton.docpad/oocss/help/components.html
    • semantic 스타일을 지속적으로 사용하자
    • 내부에 종속되지 않도록 모듈을 디자인하자
    • 코드를 유연하게 (width는 container가 제어하고, height은 contents가 제어하도록)
    • Grid를 사랑하는 습관을 갖자. http://jsfiddle.net/inuitcss/CLYUC/l
    • 선택자(selector) 사용은 최소화하자
    • 여러개의 클래스를 적용하여 확장성을 열어두자
    • CSS Lint를 사용해서 코드를 검사하자
    • 구조와 스킨을 독립적으로 관리(위에서 설명)
    • 컨테이너와 컨텐츠를 구분하자(위에서 설명)
    • Reset and fonts를 사용하자 (ex. YUI)
  • 나쁜 습관
    • 의존적인 스타일을 피하자
      .class p{…}
      
    • css에 html 태그를 적지 말자
      div.classname{…}
      p.classname{…}
      
    • ID 사용은 피하자
    • 모든 이미지를 스프라이트 하지 말자
    • 높이를 고정 시킨 상태에서의 정렬을 피하자
    • 텍스트를 이미지로 사용하지 말자
    • 너무 이른 최적화는 피하자
    • 쓸모 없는 것을 두 번 반복해서 사용하지 말자

참고 사이트

http://mytory.net/archives/8949/
http://www.slideshare.net/stubbornella/object-oriented-css
http://takazudo.github.io/presentation-oocss-sass/#/

결론

결론 적으로, 각각의 방법론에는 장/단점이 존재하기 때문에 프로젝트에 따라 최적의 방법론을 선택해서 쓰는 것이 중요하다.
(한 가지의 방법론만 사용하거나, 여러가지 방법론을 조합해서 사용)


13개의 댓글

Dong Il Kim · 2015년 4월 16일 3:02 오후

좋은 자료 감사합니다. 저도 얼마전에 SASS를 배워서 모듈화를 해서 분류해 놓고 재활용하는데 고민을 하고 있습니다. 예시를 조금 더 같이 보여주시면 모임에 참여하지 않은 사람도 잘 알아 들을 수 있을것 같습니다. 🙂

Hanur Lee · 2015년 4월 16일 3:18 오후

NTS 블로그는 사랑입니다!!. 좋은 정보 공유 감사드립니다!!

Seungha Kim · 2015년 4월 17일 12:16 오전

하단의 Sass mixin & extend 비교 부분에서 좀 더 참고할 만한 자료가 있어 링크 겁니다. 이 글에서는 mixin의 손을 들어주었습니다.
https://tech.bellycard.com/blog/sass-mixins-vs-extends-the-data/
중복코드가 나쁜 주된 이유는 유지보수가 힘들기 때문인데, mixin의 경우 사람이 만지는 단계에서는 중복이 발생하지 않으므로 유지보수의 문제가 발생하지 않습니다. 또한 중복이 발생하더라도 그것이 기계가 해석하기 더 쉬운 형태라면 성능이 좋아질 것입니다. 따라서 단순히 컴파일 후 중복이 더 많이 발생한다고 해서 나쁘다고 평가하는 것은 틀린 판단입니다. 자세한 것은 위 링크를 참고해 주시기 바랍니다.

Moo hyun Lee · 2016년 3월 18일 2:30 오후

좋은 자료 감사합니다. ^^

Plusb Preco · 2016년 3월 30일 8:27 오전

감사합니다!

안형우 · 2016년 7월 5일 2:34 오후

extend는 사용하지 말고, mixin을 사용하라는 조언입니다. http://csswizardry.com/2016/02/mixins-better-for-performance/
이유: CSS 순서를 바꾼다. 연관없는 선택자를 함께 묶는다. 원하는 것만 수정하지 못하는 경우가 생기고, 금세 통제를 벗어난다. 심지어 성능도 떨어진다.
해외 글들을 보면 요즘은 extend를 안 쓰는 추세인 것 같습니다.

Sherlock Jeon · 2017년 2월 24일 10:54 오전

SMACSS 설명에 ‘l-‘ 은 접두사 (prefix)아닌가요..

ㅇㅅㅇ · 2021년 4월 17일 2:26 오후

좋은 글 감사합니다. 그런데 모든 이미지를 스프라이트 하지 말자는게 무슨 의미인지 구체적으로 설명해 주실 수 있나요?

    WIT Manager · 2021년 4월 23일 1:52 오후

    글쓴분이 퇴사하셔서 대신 답변드리면 모든 이미지 asset을 sprite로 만들어 작업하는게 아닌 상황이나 쓰임에 따라 선택하자는 의미로 보입니다 🙂

sticky · 2021년 5월 11일 4:07 오전

좋은 정보 감사합니다.
많은 도움이 되었습니다!

CSS Naming Convention – kate kim · 2018년 3월 7일 10:08 오후

[…] [CSS방법론] SMACSS, BEM, OOCSS […]

[CSS방법론] SMACSS, BEM, OOCSSWIT – NTS UIT Blog | WIT – NTS UIT Blog – Tarot's Design & Frontend Dev. · 2018년 8월 5일 4:01 오후

[…] 소스: [CSS방법론] SMACSS, BEM, OOCSSWIT – NTS UIT Blog | WIT – NTS UIT Blog […]

css 방법론 – Jinny's tutoring · 2020년 4월 23일 8:37 오후

[…] [CSS방법론] SMACSS, BEM, OOCSS […]

답글 남기기

아바타 플레이스홀더

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다