StoryBook

황태현·2021년 5월 6일
3

storybook과Atomic

목록 보기
2/3

1. storybook란?

storybook은 UI개발 도구로 데이터베이스나 서버가 연결되어있지 않더라도 확인이 가능하게 만들어 줍니다.

이를 이용해서 외부에 프로그램을 소개할 때 사용하기도 하고 내부에서 프로그램을 개발 시 문서화 등에 사용이 됩니다.

특히 환경에 구애받지 않고 UI컴포넌트가 어떻게 렌더링 되는지를 볼 수 있고 정리가 가능하므로 개발자 입장에서는 다른 개발자가 개발한 컴포넌트를 매우 쉽게 이해할 수 있습니다.

디자인 시스템

내부에서 개발자를 위한 문서화를 디자인 시스템이라 합니다.

제플린, 피그마를 이용한 Style Guide
그리고 우리가 배울 storybook를 사용해 만들 Component Library로 나눠집니다.

물론 Style Guide도 storybook로 만들 수 있으나 지금은 회사에 디자이너가 제플린, 피그마를 통해 디자인 초안을 주고 개발을 하면서 컴포넌트를 문서화를 한다는 가정을 하겠습니다.

2. 스토리북 시작하기

storybook을 사용할 때 2가지 방법이 있습니다.

  1. create-react-app이나 직접 만든 프로젝트에 StoryBook 설정
  2. StoryBook 전용 프로젝트

먼저 2번 방법으로 해보겠습니다.

mkdir storybook-tutorial
cd storybook-tutorial
yarn init -y # 또는 npm init -y
npx -p @storybook/cli sb init --type react
yarn add react react-dom # 또는 npm i react react-dom

그리고 yarn storybook or npm run storybook를 실행하면 아래와 같은 화면이 뜹니다.



폴더 구조는 이렇게 생겼습니다.

.storybook는 설정파일 stories는 storybook의 코드입니다.

우리는 react로 프로젝트를 진행할 것 이므로 폴더 구조를 변경하겠습니다.

  1. src폴더를 생성 후 stories를 이동시킵니다.

  2. .storybook에 main.js파일이 있는데 아래의 코드로 바꿔줍니다.

...
  "stories": [
    "../src/**/*.stories.mdx",
    "../src/**/*.stories.@(js|jsx|ts|tsx)"
  ],
...
  1. storybook 다시 실행해서 이전과 똑같이 나왔으면 잘 됬습니다.

3. 첫번째 컴포넌트와 스토리

이제 우리가 직접 컴포넌트를 만들고 그에 따른 스토리를 제작하겠습니다.

우선 새로운 컴포넌트를 작성해 봅시다. 저같은 경우는 src/components/Hello/Hello.js로 만들었습니다.

import React from 'react';

const Hello = (name, big) => {
    if(big) {
        return <h1>안녕하세요, {name}</h1>
    }
    
    return (
        <div>
            안녕하세요, {name}
        </div>
    );
};

export default hello;

big이면 h1태그 아니면 p태그로 출력하는 간단한 컴포넌트 입니다.

이제 그러면 스토리를 작성해 봅시다.

스토리를 작성할 때 2가지 방법이 있습니다.

1 .예전에 사용하던 storiesOf라는 API방식
2. 5.2버젼 부터는 Component Story Format(CSF)방식

여기서는 CSF방식만을 다루겠습니다.

컴포넌트와 똑같은 위치에 Hello.stories.js라는 파일을 만들어줍니다.

import React from 'react';
import Hello from './Hello';

export default {
  title: 'components|basic/Hello', // 스토리북에서 보여질 그룹과 경로를 명시
  component: Hello // 어떤 컴포넌트를 문서화 할지 명시
};

export const standard = () => <Hello name="Storybook" />;
export const big = () => <Hello name="Storybook" big />;

이제 컴포넌트와 스토리가 완성되었습니다. 그러면 스토리북 확인해 봅시다.

두 가지 버젼으로 잘 나왔습니다.
이렇게 각 스토리를 따로 실행하지 않고 각 브라우저로 확인하는 것이 가장 기본적인 storybook의 기능입니다.

여기에 다양한 애드온(Addon)을 사용하면 더 다양하고 편리한 기능을 사용할 수 있습니다.

4. StoryBook의 에드온들

Knobs 애드온

Knobs 애드온은 컴포넌트의 props를 스토리북에서 바꾸고 반영하는 애드온입니다.

애드온을 설치하고

$ yarn add --dev @storybook/addon-knobs
# 또는 npm install --save-dev @storybook/addon-knobs

.storybook/main.js에 코드를 수정해 줍니다.

...
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-knobs"
  ]
...

모든 애드온은 여기서 관리하게 됩니다. 방금전 설치한 addon-knobs를 추가했습니다.
그리고 Hello.stories.js에 코드를 추가 해줍니다.

import React from 'react';
import Hello from './Hello';
import { withKnobs } from '@storybook/addon-knobs';

export default {
  title: 'components|basic/Hello', // 스토리북에서 보여질 그룹과 경로를 명시
  component: Hello, // 어떤 컴포넌트를 문서화 할지 명시
  decorators: [withKnobs] // 애드온 적용
};
...

이제 추가를 했으니 사용해보겠습니다.

...
export const hello = () => {
    // knobs 만들기
    const big = boolean('big', false);
    const name = text('name', 'Storybook');
    return <Hello name={name} big={big} />;
};
hello.story = {
name: 'Default'
};
...

hello라는 함수를 만들고 컴포넌트의 props를 타입과 기본값을 정의하고 컴포넌트를 리턴해줍니다. 그리고 스토리의 이름도 정의해주고 실행해주면 아래와 같은 화면이 띄워집니다.

이젠 우리가 직접 속성을 변경할 수 있습니다.

지금은 text와 boolean 두가지만 사용했지만 이 외에도 많은 속성이 있습니다.

  • text : 텍스트를 입력 할 수 있습니다.
  • boolean : true/false 값을 체크박스로 설정 할 수 있습니다.
  • number : 숫자를 입력할 수 있습니다. 1~10과 같이 간격 설정도 가능합니다.
  • color : 컬러 팔레트를 통해 색상을 설정 할 수 있습니다.
  • object : JSON 형태로 객체 또는 배열을 설정 할 수 있습니다.
  • array : 쉼표로 구분된 텍스트 형태로 배열을 설정 할 수 있습니다.
  • button : 특정 함수를 실행하게 만드는 버튼을 만들 수 있습니다.

그 외의 스펙들은 여기에서 확인합시다.

Knobs 를 사용 할 때 넣어주어야 하는 주요 인자로는 Knobs 의 이름, 기본값 그리고 GROUP ID 가 있습니다. GROUP ID 의 경우 생략해도 됩니다.

Actions 애드온

이 애드온은 컴포넌트를 통해서 특정 함수가 호출될 때 어떤 함수가 호출됐는지 그리고 어떤 파라미터를 넣어서 호출했는지에 대한 정보를 확인할 수 있습니다.

간단한 함수 호출부터 리액트 라우터 주소 호가인, 리덕스 스토어의 dispatch되는 액션의 정보를 볼 수 도 있습니다.

참고로 이 애드온은 기본적으로 적용이 되어있기 때문에 따로설치할 필요가 없습니다.

그러면 우리가 만든 컴포넌트에 클릭 이벤트를 넣어봅시다.

import React from 'react';

const Hello = ({ name, big, onHello, onBye }) => {
  return (
    <div>
      {big ? <h1>안녕하세요, {name}!</h1> : <p>안녕하세요, {name}!</p>}
      <div>
        <button onClick={onHello}>Hello</button>
        <button onClick={onBye}>Bye</button>
      </div>
    </div>
  );
};

export default Hello;

가상으로 props로 받은 이벤트를 버튼에 넣어주고
우리가 만든 Default 스토리의 리턴값을 아래와 같이 바꿔줍니다.

...
export const hello = () => {
...
  return (
    <Hello
      name={name}
      big={big}
      onHello={action('onHello')}
      onBye={action('onBye')}
    />
  );
...

액션을 정의할 때 action('액션이름')으로 간단하게 작성이 가능합니다. 스토리북에서 클릭을 하면 아래와 같은 화면이 나옵니다.

Docs 애드온

디자인 시스템에서 가장 중요한 것은 문서화입니다.
그렇기 떄문에 MDX형식으로 문서를 작성할 수 있게 해주고 props와 주석을 기반으로 자동으로 문서를 작성하는 Docs 애드온은 꼭 사용해 줍시다.

yarn add --dev @storybook/addon-docs
# 또는 npm install --save-dev @storybook/addon-docs
...
  "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-knobs",
    "@storybook/addon-docs"
  ]
...

설치 후 .story/main.js에 정의해줍니다.
그리고 storybook를 다시 실행하면 아래와 같은 Docs가 뜨게 됩니다.

위 그림에서 props가 제대로 설정되지 않고
No inputs found for this components. Read the docs라 써있습니다.
이 부분은 TypeScript나 prop-types를 사용해야 합니다.
아직 여기서는 TypeScript를 사용하지 않으므로 prop-types를 사용하고 기본값도 defaultProps로 설정해보겠습니다.

Hello.js 컴포넌트에 타입을 지정해보겠습니다.

import React from 'react';
import PropTypes from 'prop-types';


const Hello = ({ name, big, onHello, onBye }) => {
  return (
    <div>
      {big ? <h1>안녕하세요, {name}!</h1> : <p>안녕하세요, {name}!</p>}
      <div>
        <button onClick={onHello}>Hello</button>
        <button onClick={onBye}>Bye</button>
      </div>
    </div>
  );
};


Hello.propTypes = {
    /** 보여주고 싶은 이름 */
    name: PropTypes.string.isRequired,
    /** 이 값을 `true` 로 설정하면 h1 태그로 렌더링 됩니다. */
    big: PropTypes.bool,
    /** Hello 버튼 누를 때 호출할 함수 */
    onHello: PropTypes.func,
    /** Bye 버튼 누를 때 호출할 함수 */
    onBye: PropTypes.func
};

Hello.default = {
    big: false,
}

export default Hello;

/** */주석을 통해 추가적인 설명을 추가할 수 있습니다.
그럼 아래와 같은 그림이 나오게 됩니다.

컴포넌트에 부제목 및 설명 넣기

Hello 컴포넌트가 어떠한 역할을 하는 컴포넌트인지 잘 모르기 때문에 추가적인 설명을 넣는 방법을 알아보겠습니다.
Hell.stories.js를 수정하겠습니다.

...
export default {
  title: 'components|basic/Hello', // 스토리북에서 보여질 그룹과 경로를 명시
  component: Hello, // 어떤 컴포넌트를 문서화 할지 명시
  decorators: [withKnobs], // 애드온 적용
  parameters: {
    componentSubtitle: "'안녕하세요'라 보여지는 컴포넌트"
  }
};
...

parameters객체에 componentSubTitle을 추가했습니다. 그러면 아래의 그림과 같이 부제목이 표기됩니다.


이번에는 추가적인 설명을 작성해보겠습니다.
...
/**
 * props: {name, big, onHello, onBye}
 * 
 * - `name`: 안녕하세요 다음에 나올 텍스트 값
 * - `big`: h1태그 적용 여부
 * - `onHello`, `onBye`: 버튼 이벤트
 */
const Hello = ({ name, big, onHello, onBye }) => {
...







출처
1. https://storybook.js.org/docs/react/get-started/introduction
2. https://velog.io/@velopert/design-system-using-typescript-and-storybook

profile
안녕하세요 프론트엔드 개발자를 희망하는 황태현입니다.

0개의 댓글