디자인과 프론트엔드 개발 그리고 문서화 -스토리북 도입에 관한 고찰-

2021. 3. 19. 11:24개발노트/front-end

안녕하세요. mysterico 의 joshua 입니다. 미스테리코에서 프로젝트를 진행하면서 점점 늘어나는 컴포넌트와 화면들을 보면서,어떻게 하면 많은 컴포넌트와 UI 를 효율적으로 관리하면서도 늘 멋진 디자인을 해주시는 디자인팀분들과 더 원활한 소통을 할 수 있을까? 라는 고민을 가지게 되었습니다.

프론트엔드 개발을 하면서 디자인과 개발의 생산성을 높여주기 위해 문서화는 선택이 아닌 필수지만 지금 하고 있는 방식보다 더 좋은 것이 있을 것이라는 생각이 들어 관심을 가지고 찾아보게 되었습니다.

여기 저기 둘러보다보니 문서화에 중요성을 나타내는 가장 인상 깊었던 문구가 있습니다.

"If you don't document it, it doesn't exist"

우리가 아무리 재사용이 쉬운 컴포넌트를 만들고, 코드 상에 주석을 작성을 하고 그래도 문서화가 되어있지 않다면 그것은 디자인 시스템이라고 부를 수 없는 것입니다.

이처럼 중요한 문서화를 더욱 편하고 효율적으로 관리하기 위해 요즘 핫?한 스토리북에 도입을 고려하게 되었습니다.

 

이 전까지의 공통 컴포넌트에 대한 스타일 가이드 작업은 구현에 우선순위가 늘 밀려서 간단하게 컴포넌트를 모아놓은 페이지를 하나 만들고 그 안에서 동작할 수 있는 정도로 구현해서 공유 드렸었지만, 앞으로도 계속 늘어날 컴포넌트와 페이지를 위해 스토리북으로 간단한 예시를 만들어보면서 정리하는 시간을 가져 보려고 합니다!

 

 

그렇다면 스토리북이란 무엇일까요?

스토리북은 React, Vue, Angular 등을 위해 분리 된 UI 컴포넌트를 개발하기위한 오픈 소스 도구입니다.

스토리북에서 말하는 스토리북은 효율적으로 UI 와 각각의 컴포넌트를 체계적이고 효율적으로 관리할 수 있는 툴로 비즈니스 로직과 컨텍스트로부터 UI 컴포넌트를 독립적으로 분리하여 만들수 있도록 도와줍니다.

 

스토리북은 컴포넌트의 재사용을 위해 문서화하고 버그를 방지하기 위해 컴포넌트를 시각적으로 바로 확인하고 테스트 하는 데 도움이 됩니다 . 또한 반응형 레이아웃을 미세 조정하거나 접근성을 확인하는 데 도움이 되는 애드온 시스템도 가지고 있으면 여러 에드온을 통해 더욱 정교한 문서화가 가능합니다.

또한 스토리북은 가장 널리 사용되는 JavaScript UI 프레임 워크와 통합됩니다.

이제 서론은 여기서 마치고 리액트 환경에서 간단한 예시를 만들어보겠습니다.


공식문서를 따라 cra 로 프로젝트를 생성하고 다음 명령어를 실행합니다.

Add Storybook:

npx -p @storybook/cli sb init

Start the component explorer on port 6006:

yarn storybook

 

이제 6006 포트에서 스토리북를 시작할 수 있습니다. 이제 프로젝트 디렉토리를 보면

.storybook 폴더와 src 내부에 stories 폴더가 생성되어 있는 것을 볼 수 있습니다.

.storybook 에 있는 main.js 에서는 사용할 에드온을 추가하고 story 파일의 경로를 추가해 읽어드릴 수 있습니다.

preview.js 파일의 경우 stories의 렌더링을 설정합니다. preview.js 는 어느 stories의 로딩도 책임지지 않지만, 주 목적은 global parameters와 decorators를 추가하는 것입니다.

이제 우리는 스토리로 확인할 간단한 컴포넌트를 하나 만들어보겠습니다.

import React from "react";

const Mysterico = ({ name, big }) => {
  if (big) {
    return <h1>안녕하세요, 미스테리코 {name}입니다!</h1>;
  }
  return <p>안녕하세요, 미스테리코 {name} 입니다!</p>;
};

export default Mysterico;

props 로 name 과 big 이라는 값을 받고 받은 값에 따라 텍스트를 추가하거나 다른 태그를 리턴하는 간단한 컴포넌트입니다.

이제 해당 컴포넌트를 스토리에 추가하기 위해 Mysterico.stories.js 파일을 생성합니다.

아까 만들어둔 미스테리코 컴포넌트를 불러오고 스토리를 작성합니다.

이 전 버전까지는 storiesOf 로 컴포넌트를 추가했었는데 이번에 Component Story Format (CSF) 가 추가되면서 (자주 쓰이는 에드온이 기본 에드온으로 들어 간것도 👍) 더욱 간결하게 스토리를 추가할 수 있습니다.

// storeisOf
storiesOf("Mysterico/Mysterico", module)
  .add('default', () => <Mysterico  />
  .add('name', () => <Mysterico name='joshua' />

// CSF
export default { title: "Mysterico/Mysterico" }
export const default = () => <Mysterico  />
export const name = () => <Mysterico name='joshua' />

여기서 추가로 컴포넌트의 arguments 를 더 쉽게 넘겨주기 위해 Template.bind({}) 를 사용해 보겠습니다.
Template.bind({}) 를 사용하면 코드 중복을 줄이며 손 쉽게 복사본을 만들 수 있습니다.

// MyComponent.stories.js
import React from "react";
import Mysterico from "../Mysterico";

const storyOption = {
  title: "Mysterico/Mysterico",
  component: Mysterico,
};

export default storyOption;

const Template = (args) => <Mysterico {...args} />;

export const Primary = Template.bind({});

export const IsBig = Template.bind({});
IsBig.args = {
  big: true,
  name: "",
};

export const HasName = Template.bind({});
HasName.args = {
  name: "Joshua",
};

export const BigHasName = Template.bind({});
BigHasName.args = {
...HasName.args,
  big: true,
};

이제 스토리로 가보면 storyOption 에서 설정한 title 안에 해당 컴포넌트에 스토리가 생성된 것을 확인할 수 있습니다!

상단 탭에서 Docs 는 작성한 스토리를 한 눈에 문서화에서 확인할 수 있고 확대, 축소, light/dark 모드, 눈금, 디바이스 화면 설정 등 여러 옵션을 설정할 수도 있습니다. :)

이제 스토리로 가보면 storyOption 에서 설정한 title 안에 해당 컴포넌트에 스토리가 생성된 것을 확인할 수 있습니다!

상단 탭에서 Docs 는 작성한 스토리를 한 눈에 문서화에서 확인할 수 있고 확대, 축소, light/dark 모드, 눈금, 디바이스 화면 설정 등 여러 옵션을 설정할 수도 있습니다. :)

이제 스토리 디렉토리를 살펴보면 Primary 아래로는 위에서 작성한 각 상태에 따른 스토리를 모두 볼 수 있습니다.

여기까지가 기본적으로 컴포넌트를 만들고 해당 컴포넌트를 스토리에 추가하는 방법입니다!


이제는 조금 더 나아가서 에드온에 있는 controlsaction 을 알아보도록 하겠습니다.

지금 위에 미스테리코 컴포넌트만 보면 컴포넌트의 모든 상태마다 스토리를 추가해야 할까 라는 생각이 들 수도 있지만 아래 에드온 부분에 있는 control 에서 스토리 렌더 시 인자로 넘겨줬던 props 값을 직접 변경해서 컴포넌트의 변경 상태를 확인 할 수 있습니다.

props 로 받아오던 name 을 변경해 보았습니다! control 에서는 컴포넌트의 상태를 변경할 수 있는 편하고 다양한 방법을 제공합니다.

추가로 contorl 에서 제공하는 몇가지 방법 중 컴포넌트의 색상을 변경해 보겠습니다!

const storyOption = {
  title: "Mysterico/Mysterico",
  component: Mysterico,
  argTypes: {
    color: { control: 'color' },
    backgroundColor: { control:'color'}
  },
};

스토리 옵션에 argTypes 에서 contorl 값을 color 로 설정하고 미스테리코 컴포넌트도 props 로 color, backgroundColor 를 받을 수 있게 수정해주겠습니다. (아래의 표는 control 에서 제공하는 control 타입입니다.)

이제 다시 스토리로 돌아가보면 하단에 color picker 로 색상을 변경할 수 있는 control 이 추가되어 있는 것을 확인하실 수 있습니다!

+ control 에드온에 관한 doc 를 추가로 첨부합니다. :)

storybook.js.org/docs/react/essentials/controls

 

Controls

Storybook is an open source tool for developing UI components in isolation for React, Vue, and Angular

storybook.js.org

이제 마지막으로 Action 에드온을 살펴보겠습니다. Action 에드온의 경우 컴포넌트를 통하여 특정 함수가 호출됐을 때 어떤 함수가 호출됐는지, 그리고 함수에 어떤 파라미터를 넣어서 호출했는지에 대한 정보를 확인 할 수 있게 해줍니다. 

 

이제 미스테리코 컴포넌트에 버튼을 만들고, storyOption 에 onClick 을 추가하고 action 이름을 정해주고 클릭해 보겠습니다!

const storyOption = {
  title: "Mysterico/Mysterico",
  component: Mysterico,
  argTypes: {
    onClick: { action: 'clicked' },
    color: { control: 'color' },
    backgroundColor: { control:'color'}
  },
};

 

 

이제 하단 Action 탭에서 발생한 이벤트 로그를 확인할 수 있습니다.


 

마치며,

 

간단한 예제를 만들어 보면서 느낀 것은 기존처럼 한 페이지에 컴포넌트를 모아놓고 보는 방식보다 좋은 가독성과 문서화, 그리고 옵션 등 너무나 많은 장점을 가지고 있는 것 같습니다! 

개발자가 아니라도 컴포넌트를 쉽게 이해하고 상태를 변경시키며 테스트를 할 수 있어 타 팀분들과도 원활하게 UI 와 컴포넌트에 관해 소통할 수 있을 것 같아 디자인과 개발의 생산성을 높일 것이라 생각해서 미스테리코에서도 조만간? 도입을 고려하고 있는 중입니다.

 

빠른 시일 내에 미스테리코의 멋지고 예쁜 컴포넌트들로 가득찬 스토리를 보여드릴 수 있으면 좋겠습니다! 감사합니다 :)