Vue.js설계 및 Atomic Design

kameals·2020년 2월 20일
7
post-thumbnail

개요

회사에서는 프론트 프레임워크로 Vue를 채택하고 있습니다.
현재 운용 중인 설계법 및 아토믹 디자인에 대해서 정리하고자 합니다.

Atomic Design이란?

화면을 구성하는 요소를 원자(atom), 분자(molecule), 유기체(oranism), 템플릿(template), 페이지(page)로 5계층으로 나눈 것으로, 최종적으로는 UI와 UI의 기초가 되는 디자인시스템을 동시에 작성하는 설계방법입니다.

왜 Atomic Design인가?

Atomic Design의 장점

  • 작성 과정에서 추상적인 UI구조를 구체적인 UI로 재빠르게 옮겨가며, 화면 전체와 개별 UI부품들의 구조를 단계별로 비교함으로써, UI디자인 시스템을 동시에 작성하는 것이 가능합니다.
  • 컴포넌트의 디자인 변경에 대처하기 쉬워지며, 재사용성이 높아집니다.
  • CSS선택자의 명시도가 평탄해집니다.
    ( 명시도, Lesson #7 CSS 사용시 반드시 알아야 할것, 명시도참고 )

Atomic Design의 단점

  • 도입하기까지 시간이 걸린다.
  • 컴포넌트 수가 많아진다.

몇가지 단점이 있음에도 불구하고, Atomic Design을 도입한 이유는 현재 제품 특성상 공통으로 사용하는 부분이 많다는 점과 재사용성이 높아진다는 점, 그리고 UI와 관련하여 디자인팀과의 커뮤니케이션 비용이 줄어든다는 점입니다.

Atomic Design을 반영한 Vue컴포넌트 설계

공통

  • 전체 컴포넌트는 atom<molecule<organism<template<page의 5단계로 나눈다. (오른쪽으로 갈수록 입자의 크기가 커진다.)
  • 컴포넌트는 자신보다 큰 입자의 컴포넌트를 의존해서는 안 된다.
    ex) organism 가 molecule 을 임포트하는 것은 가능하지만, molecule 가 organism 을 임포트해서는 안 된다.
  • 어떤 컴포넌트가 스스로 모든 처리를 완결할 수 있다면, 부모 컴포넌트는 그 처리를 알아서는 안 된다.
  • 컴포넌트는 원칙적으로 다른 컴포넌트의 스타일을 결정해서는 안 된다.
    -- 예의적으로, 부모가 자식 컴포넌트의 스타일을 네스트(nest)하여 지정하는 경우는 허용한다.
    ex) 특정 organism내에서만 존재하는 molecule의 스타일을 변경하고 싶은 경우
  • 자식 컴포넌트는 자신을 호출한 부모 컴포넌트의 스타일은 알 수 없다.
  • page 이외의 컴포넌트는 원칙적으로 store 에 액세스할 수 없다. 유저가 입력한 값 등을 store에서 관리하는 경우는 부모(page)에게 이벤트로 전달하여, 부모가 핸들링한다.
  • props가 전달받은 값은 반드시 type과 required를 지정한다.
  • 여러 page에 걸쳐 값을 보유하고 있는 경우 이외에는 store에 기입해서는 안 된다.
  • 파일명은 파스칼케이스로 통일한다.

atom

  • 하나의 UI 기능과 그 이상 쪼갤 수 없는 단위.
  • css는 컴포넌트 단위로 구현한다.
  • vuex의 store에는 접근할 수 없다.

ex) Button.vue

<template>
    <button @click="$emit('buttonClick')">{{ text }}</button>
</template>
<script>
    export default {
        props: {
            text: {
                type: String,
                default: '전송',
            },
        },
    }
</script>

molecule

  • 복수의 atom으로 구성되어 추상화된 파트. (입력폼의 아이템 등)
    atom과의 차이로는 atom이 UI로써 하나의 기능을 제공한다면, molecule은 어떤 목적을 가지고 있다는 점이다.
    ex) 텍스트박스나 버튼은 그 하나만으로는 입력기능만을 가지는 atom이지만, 유저가 검색할 수 있게 해준다는 목적으로 조합된 검색창이라고 한다면 molecule이다.
  • vuex의 store에는 접근할 수 없다.

ex) SearchBox.vue

<template>
    <div>
        <TextBox />
        <Button
          text="검색"
          @buttonClick="search" />
    </div>
</template>
<script>
   @import TextBox from '경로';
   @import Button from '경로';
    export default {
        components: {
            TextBox,
            Button,
        },
        methods: {
            search() {
                // 처리
            },
        }
    } 
</script>

organism

  • 복수의 molecule들로 구성되며, 필요한 경우 atom과 그 외 organism으로 구성되기도 한다.
    ex) 헤더, 로고, 내비게이션, 검색창 등의 여러 목적을 가진 컴포넌트(=molecule)가 조합되어 하나의 컴포넌트를 구성한다.
  • 그 organism으로 완결할 수 있는 처리는 store에 접근할 수 있다.
    ex) 헤더에서 유저의 이름을 store로부터 취득하는 경우.

template

  • 동일한 구성의 페이지가 여러개 존재하는 경우 사용한다.
  • Vue의 slot을 사용하여 안에 내용물을 넣는 용도로 사용한다.
  • 템플릿에서 해결해야 하는 처리의 경우 store에 접근할 수 있다.

page

  • 페이지 고유의 구체적인 값을 vue의 slot이나 디렉티브를 사용하여 자식 컴포넌트에 전달한다.
  • 잠정 대응이나 특정 페이지에서만 사용하는(재사용하지 않는 것을 전제로 하는) UI는 여기에 기술하는 것이 좋다.
    page는 기본적으로 재사용하지 않는다.
  • 예외) 두개 이상의 URL에서 동일한 페이지에 접근하는 경우는 예외로 한다.
  • store에 접근할 수 있다.

문제점

css를 어디에 기술하는가에 대해서는 문제가 있다.

.vue 확장자를 가진 파일에 컴포넌트단위로 스타일을 기술할지, 또는 .css(.scss)파일에 스타일을 기술할지에 관하여

.vue에 기술하는 장점

  • 컴포넌트단위로 스코프를 설정할 수 있으므로, 다른 컴포넌트에 스타일을 오염시키기 어렵다.
  • 하나의 컴포넌트당 하나의 파일로 분할하므로, 코드 가독성이 높다.
  • 관심의 분산과 파일의 분산이 일치하므로, 일관성 있고 보수성이 높다.
  • 불필요한 네스트가 발생하기 어렵다.

.vue에 기술하는 단점

  • 전체를 컴포넌트화하지 않는 경우, 어떤 컴포넌트가 해당 스타일을 가지게할 지 문제가 생긴다. 예를 들어 atom이 없는 경우, atom에 해당하는 스타일을 molecule에 기술할지 organism에 기술할지 등.
  • 전체를 컴포넌트화할 경우, 컴포넌트의 수와 파일의 갯수가 거대해진다.

.scss에 기술하는 장점

  • 해왔던대로 하면 되기 때문에, 학습비용이 거의 없다. 기존에 존재하던 scss를 그대로 사용할 수 있다.
  • 스타일은 .scss에만 적으면 되므로, 코더가 작업하기 쉽다.

.scss에 기술하는 단점

  • 관심의 분산과 파일의 분산이 일치하지 않으므로, 컴포넌트를 작성하고 수정할 때, html과 css(또는 js) 각각 수정해야 한다.
  • vue와 같은 스코프가 없으므로, 스타일의 오염이 발생하기 쉽다.

디렉토리 구성

목표

최종적으로는 Vue 이하에 아래와 같이 구성했다.

vue/
├ componets/
│    ├ atoms/
│    ├ molecules/
│    ├ organisms/
│    ├ pages/
│    └ templates/
├ dist/ 빌드된 결과물
├ router/  vue-router의 루터와 루트
├ store/ Vuex의store를 모듈화하여 분할하여 관리
└ index.js 여기서Vue인스턴스를 작성한다. webpack의 엔트리포인트. 다른 곳에서는 new Vue() 하지 않는다. 

참고

Atomic Design

profile
팀의 윤활유 역할이 되고 싶은 소박한 개발자입니다. 좌우명은 '밝고 바르고 튼튼하자'

0개의 댓글