프로토타이핑

프로토타이핑은 디자인에서 나타나는 패턴을 기록해서 사이트의 기초 자재를 만드는 데에 도움이 된다. 프로토타이핑은 다음과 같은 목표가 있다.

  • 상태별 모습을 확인하기
  • 지역화 때문에 깨지지 않나 확인해보기
  • 의존성 분리

Yahoo!에서는 Mustache 템플릿을 기반으로 JSON 형태로 저장한 데이터와 각 패턴에 필요한 CSS, JavaScript를 끌어와서 모듈을 컴파일해주는 프로토타이핑 엔진이 있었다.

프로젝트에 규모가 클 수록 이런 프로토타이핑 엔진이 유용하다.

소규모 프로젝트에서도 디자인 패턴은 기록해 두는 것이 좋다. (예: MindChimp).

전처리자(Preprocessors)

전처리자를 사용하면 개발자들의 인생이 쉬워진다고들 한다. 전처리자는 특수한 문법을 사용해서 작성한 파일을 CSS 파일로 컴파일해준다. 지금은 Sass와 Less가 CSS 전처리자 시장을 주도하고 있다.

Sass 설치하고 사용하기

Sass를 사용하려면 ruby 인터프리터가 깔려 있어야 한다. Sass는 ruby 패키지 관리자인 gem을 이용해서 쉽게 설치할 수 있다.

gem install sass

Sass는 Sass 문법으로 작성한 .scss 파일을 .css 파일로 컴파일해준다. 다음과 같이 입력하면 특정 디렉토리를 감시하면서, 변경된 파일이 있으면 그때그때 컴파일해준다.

sass --watch [inputdir]:[outputdir]

혹은 다음과 같이 명령줄을 입력해서 컴파일 할 수도 있다.

sass [inputfile] [outputfile]
sass --update [inputdir]

Sass의 기능들

변수

scss input:

$color: #369

body {
    color: $color;
}

.callout {
    border-color: $color;
}

result:

body {
    color: #369;
}

.callout {
    border-color: #369;
}

중첩

scss input:

.nav {
    > li {
        float: left;
        > a {
            display: block;
        }
    }
}

result:

.nav li {
    float: left; }
    .nav > li > a {
        display: block; }

Mixin(범벅?)

scss input:

@mixin border-radius ($size) {
    -webkit-border-radius: $size;
       -moz-border-radius: $size;
            border-radius: $size;
}

...

.callout {
    @include border-radius(5px);
}

result:

.callout {
    -webkit-border-radius: 5px;
        moz-border-radius: 5px;
            border-radius: 5px;
}

함수

scss input:

$btnColor: #036;
.btn { 
    background-color: $btnColor;
}
.btn:hover {
    background-color: lighten($btnColor, 20$);
}

result:

.btn {
    background-color: #003366;
}
.btn:hoveer {
    background-color: #0066cc;
}

확장

scss input:

.btn {
    display: block;
    padding: 5px 10px;
    background0color: #003366;
}
.btn-default {
    @extend .btn;
    background-color: #0066cc;
}

result:

.btn, .btn-default {
    display: block;
    padding: 5px 10px;
    background-color: #003366;
}
.btn-default {
    background-color: #0066cc;
}

#main .btn과 같은 복잡한 선택자는 사용할 수 없다.

전처리자의 함정

“큰 힘에는 큰 책임이 따른다” - 스파이더맨

전처리기는 유용하지만, 컴파일된 결과가 비대해져서 디버그하기 어려워질 수도 있다.

중첩 남용

scss input:

#sidebar {
    width: 300px;
    .box {
        border-radius: 10px;
        background-color: #EEE;
        h2 {
            font-size: 14px;
            font-weight: bold;
        }
        ul {
            margin: 0;
            padding: 0;
            a {
                display: block; 
            }
        }
    }
}

result:

#sidebar {
    width: 300px; }
    #sidebar .box {
        border-radius: 10px;
        background-color: #EEE; }
        #sidebar .box h2 {
            font-size: 14px;
            font-weight: bold; }
        #sidebar .box ul {
            margin: 0;
            padding: 0; }
            #sidebar .box ul a { 
                display: block; }

SMACSS식 스타일:

#sidebar {
    width: 300px;
}

.box { ... }
.box-header { ... }
.box-body {
    ...
    a {
        display: block; 
    }
}

확장의 남용

@extend를 사용하면 HTML 요소에 클래스를 여러개 적지 않아도 된다. 기존에는 HTML 요소에 하위 클래스 이름을 적었다면, @extend는 하위 클래스의 이름을 공통된 스타일 선언부로 보내준다. @extend를 쓸 경우 하위 모듈의 이름을 잘 지어야 한다. btn의 하위 모듈 이름이 small이라면 나중에 볼 때 혼란스럽다. 뭐가 작다는 거지? btn-small이라고 명명하면 나중에 봐도 쉽게 알 수 있다.

@extend는 하위 모듈을 만들기 위한 명령어다. 서로 관련 없는 두 모듈에 @extend를 써선 안된다.

.box {
    border-radius: 5px;
    box-shadow: 0 0 3px 0 #000000;
    background-color: #003366;
}
.btn {
    @extend .box;
    background-color: #0066cc;
}

이처럼 모듈의 상호 의존성을 심화시키면 적시(just-in-time) CSS를 구현하기도 힘들어 진다.

SMACSS식 확장은 그냥 요소에 클래스 이름을 여러개 적는 것이다.

<a class="btn btn-default">My button</a>

이렇게 하면 모듈의 원형을 쉽게 알 수 있다. 그리고 원형에는 ‘-‘이 없기 때문에 HTML 마크업에서도 눈에 잘 띈다.

(내 개인적인 생각으로도, SMACSS의 작명 규칙에선 컴포넌트에도 ‘-‘를 붙이고, 하위 모듈에서도 ‘-‘을 붙이기 때문에, 클래스 이름을 여러개 쓰는 것이 하위 모듈 이름과 컴포넌트 이름을 구분하는 데에도 어느 정도 도움이 되지 않을까 싶다.)

Mixin 남용

scss input:

@mixin theme-border {
    border: 2px solid #039;
    border-radius: 10px;
    background: #EEE;
}

.callout {
    @include theme-border;
}

.summary {
    @include theme-border;
}

result:

.callout {
    border: 2px solid #039;
    border-radius: 10px;
    background: #EEE;
}

.summary {
    @include theme-border;
}

SMACSS식 스타일:

.theme-border { ... }
.callout { ... }
.summary { ... }

SMACSS식 마크업:

<div class="callout theme-border"></div>
<div class="summary theme-border"></div>

전처리기 제대로 활용하기

상태 기반 중첩 미디어 쿼리

scss input:

.nav > li {
    width: 100%;
    @media screen and (min-width: 320px) {
        width: 100px;
        float: left;
    }
    @media screen and ( min-width: 1200px) {
        width: 250px;
    }
}

result:

.nav > li {
    width: 100%; }
@media screen and (min-width: 320px) {
    .nav > li { ... } }
@media screen and (min-width: 1200px) {
    .nav > li { ... } }

파일 관리 규칙

  • 기초 규칙은 파일을 따로 둔다
  • 레이아웃 파일도 따로 두고, 거대 레이아웃은 한 번 더 분리할 수 있다.
  • 각 모듈별로 파일을 둔다.
  • 전역 상태도 따로 파일을 둔다.
  • 모듈 파일에는 레이아웃과 모듈 상태, 모듈에 영향을 미치는 미디어 쿼리를 둔다.

이런 식으로 파일을 분리해두면 프로토타이핑을 하기 용이하다.

변수 선언이나 Minxin이 있는 전처리자 전용 규칙들은 따로 파일을 둬야 한다.

예시:

layout/
    grid.scss
    alternate.scss
module/
    callout.scss
    bookmarks.scss
    btn.scss
    btn-compose.scss
base.scss
states.scss
satates.scss
site-settings.scss
mixins.scss

그리고 각 파일을 결합하는 마스터 파일을 둔다.

@import
    "site-settings",
    "mixins",
    "base",
    "states", 
    "layout/grid",
    "module/btn",
    "module/bookmarks",
    "module/callout";

그러면 전처리자가 이것을 하나의 파일로 컴파일해준다.

런칭 준비가 완료되면 CSS 파일을 압축해서 배치한다.

sass -t compressed master.scss master.css