Ideveloper's
Thinking

ideveloper
Front end Developer who steadily study
Apr 25, 2020 - 8 min read

storybook 잘 활용하기

🎬 시작하기에 앞서

Storybook은 UI 컴포넌트 개발을 할때 뛰어난 UI를 체계적이고 효율적으로 구축 할 수 있도록 도와주는 유용한 tool입니다. 이 포스팅에서는 storybook 사용과 관련해서는 설명하지 않고,이미 사용하고 있는 storybook을 어떻게 잘 활용할지에 대한 몇가지 방법들에 대해 포스팅 하겠습니다. 또한 storybook 5.2 버전 이상에서는 Component Story Format (CSF) 형식으로 stories를 작성하도록 권장하고 있는데요, 이 환경 에서의 활용방법 위주로 포스팅 된 점 참고 부탁드립니다.

image


Addon 관련

storybook에서는 아래에서 볼수 있듯, 다양한 기능들을 활용할 수 있게 공식적으로 addon들을 제공하고 있습니다. 그 중 유용하게 사용한 몇가지 addon들을 소개해 드리겠습니다.

image

📱 storybook viewport addon

image

프론트엔드 개발을 하다보면, 다양한 반응형에 대응을 해야할 때가 있습니다. 따라서, 스토리북을 활용하여 개발을 할때에도 이러한 반응형 UI에 따른, 컴포넌트의 스토리를 확인해야 할 경우들이 있는데요. 이 때 유용하게 사용할 수 있는 addon이 viewport addon 입니다.

설치

npm i --save-dev @storybook/addon-viewport

yarn add -D @storybook/addon-viewport

설정방법

module.exports = {
  addons: ["@storybook/addon-viewport/register"],
};

제공하는 기능은 아래와 같이 요약할 수 있습니다.

  • 다양한 viewport 설정할수 있게 configuration 하기
  • storybook defaultViewport 적용하기
  • 개별 컴포넌트 story별 viewport 적용하기

- 다양한 viewport 설정할수 있게 configuration 하기

맨처음, storybook viewport addon을 설정하게 되면 이곳 에 있는 MINIMAL_VIEWPORTS 들만 보여지게 됩니다.

//storybook/addons/viewport/src/defaults.ts
export const MINIMAL_VIEWPORTS: ViewportMap = {
  mobile1: {
    name: "Small mobile",
    styles: {
      height: "568px",
      width: "320px",
    },
    type: "mobile",
  },
  mobile2: {
    name: "Large mobile",
    styles: {
      height: "896px",
      width: "414px",
    },
    type: "mobile",
  },
  tablet: {
    name: "Tablet",
    styles: {
      height: "1112px",
      width: "834px",
    },
    type: "tablet",
  },
};

따라서, 좀 더 다양한 viewport에서 story들을 확인하고 싶다면 storybook에서 제공하는 INITIAL_VIEWPORTS를 활용해 수정해주어도 되고,

// .storybook/preview.js

import { addParameters } from "@storybook/react";
import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport";

addParameters({
  viewport: {
    viewports: INITIAL_VIEWPORTS,
  },
});

아래와 같이 viewport 리스트를 custom해 넣어주어도 됩니다.

import { addParameters } from "@storybook/react";

const customViewports = {
  kindleFire2: {
    name: "Kindle Fire 2",
    styles: {
      width: "600px",
      height: "963px",
    },
  },
  kindleFireHD: {
    name: "Kindle Fire HD",
    styles: {
      width: "533px",
      height: "801px",
    },
  },
};

addParameters({
  viewport: { viewports: customViewports },
});

- defaultViewport 적용하기

아래와 같이 default로 보여지고 싶은 viewport를 정해 넣어주기만 하면됩니다. 유의할점은 적용되어 있는 viewportList 내에서 적용을 해야한다는 점입니다.

맨 처음엔 이곳의 MINIMAL VIEWPORTS 로 리스트들이 적용되어 있어, 이 안에서 적용을 해주어야 하고, 만약 INITIAL_VIEWPORT를 viewports에 적용해 주었다면, iphonex, iphone6 등등 다양한 viewport를 default viewport로 적용이 가능해집니다.

맨 처음 설정되어있는 viewport에서 default viewport 적용

// storybook/preview.js

// 맨 처음 설정되어있는 viewport에서 default viewport 적용
import { addParameters } from "@storybook/react";

addParameters({
  viewport: {
    defaultViewport: "mobile1",
  },
});

스크린샷 2020-05-01 오후 6 19 14

추가한 viewport가 있을때 default viewport 적용

// 추가한 viewport가 있을때 default viewport 적용
import { addParameters } from "@storybook/react";
import { INITIAL_VIEWPORTS } from "@storybook/addon-viewport";

addParameters({
  viewport: {
    viewports: INITIAL_VIEWPORTS,
    defaultViewport: "iphonex",
  },
});

스크린샷 2020-05-01 오후 6 18 52

- 개별 컴포넌트 story별 viewport 적용하기

전체 프로젝트에 적용하지 않고 각각의 story별로, 데스크탑에서 쓰는 컴포넌트라면 데스크탑 viewport를, 모바일에서만 쓰는 컴포넌트라면 모바일 viewport를 적용할수도 있게 됩니다. 물론,여기서도 역시 default viewport로 설정한 key가 적용한 viewport list에 있어야 합니다.

개별 story 파일

export default {
  title: 'Stories',
  parameters: {
    viewport: { defaultViewport: 'iphone6' },
  };
};

export const myStory = () => <div />;
myStory.story = {
  parameters: {
    viewport: { defaultViewport: 'iphonex' },
  },
};

🔧 storybook knobs addon

knobs addon은 다양한 input들을 동적으로 넣어주어 컴포넌트와 상호작용 할 수 있도록 도와주는 addon입니다. 또한 넘겨준 prop 에 따라 어떤 결과물을 보여주는지 바로바로 확인하고 싶을 때 Knobs 를 사용하면 매우 유용합니다.

설치

npm i --save-dev @storybook/addon-knobs

yarn add @storybook/addon-knobs --dev

설정방법

.storybook/main.js 파일

module.exports = {
  addons: ["@storybook/addon-knobs/register"],
};

사용가능한 knobs들은 아래와 같은데요, available knobs section을 가시면 사용가능한 knobs들에 대한 더 자세한 설명을 볼 수 있습니다.

  • text
  • boolean
  • number
  • number bound by range
  • color
  • object
  • array
  • select
  • radio

아래는 text와 object knobs를 사용하여 테스트한 예제입니다.

import React from "react";
import { withKnobs, text, object } from "@storybook/addon-knobs";

import Button from "./index";

export default {
  title: "DesignSystem|atoms/Button",
  decorators: [withKnobs],
  component: Button,
};

export const defaultButton = () => {
  const styleObj = object("style object", {
    backgroundColor: "#ffffff",
    color: "#000000",
  });

  return (
    <Button style={styleObj}>{text("버튼텍스트", "Hello Storybook")}</Button>
  );
};

아래 첨부한 예제에서 확인할수 있듯, 텍스트와 object가 동적으로 스토리북 상에서 바뀌는 것을 확인 할 수 있습니다.

5월-01-2020 19-04-12

이러한 다양한 knobs들을 토대로 UI 컴포넌트를 테스트 해볼 수 있게 되는데, Storybook 공식 knobs 예제 사이트에 가시면 다양한 활용 예제들을 확인 할 수 있습니다.

📲 a11y addon

접근성이 좋은 애플리케이션이란 모든 사람이 앱을 이해하고 탐색하고 상호 작용할 수 있음을 의미합니다. 온라인에서는 탭 키 및 screen reader를 사용하여 사이트를 탐색하는 등의 콘텐츠에 액세스 할 수있는 방법등을 제공하는것을 의미하는데요, 이러한 접근성과 관련해 UI 컴포넌트들을 접근성있게 개발할수 있도록 도와주는 a11y addon이라는 addon이 있습니다. 이를 확인해 볼수 있는 간단한 예제와 함께 설명을 드리겠습니다.

관련해서 읽어보면 좋을 글

설치

npm i --save-dev @storybook/addon-a11y

yarn add @storybook/addon-a11y --dev

설정방법

.storybook/main.js 파일

module.exports = {
  addons: ["@storybook/addon-a11y/register"],
};
import React from "react";
import { withKnobs, text, object } from "@storybook/addon-knobs";
import { withA11y } from "@storybook/addon-a11y";

import Button from "./index";

export default {
  title: "DesignSystem|atoms/Button",
  decorators: [withKnobs, withA11y],
  component: Button,
};

export const accessible = () => <button>Accessible 버튼</button>;

export const inaccessible = () => (
  <button style={{ backgroundColor: "red", color: "darkRed" }}>
    Inaccessible 버튼
  </button>
);

accsible한 버튼은 accsessible 테스트를 통과 한 반면, 스크린샷 2020-05-01 오후 7 26 08

아래와 같이 시각적으로 적절히 배경색과 글자색이 적용되지않은 버튼은 아래와 같은 경고가 뜨게 됩니다.

뜬 경고에 대해 간단히 간단히 요약하자면, 글꼴의 색과 문서의 배경 색이 어느 정도의 명도 대비를 지녀야 하는지에 대한 지침인데요, 화면에서 볼 수 있듯 배경색과 글꼴색이 적절히 대비되지 않아 시각적 접근성에 위배된다고 경고를 하게됩니다.

스크린샷 2020-05-01 오후 7 26 12

따라서 배경색을 적절히 바꿔주면 아래와 같이 통과를 하게 됩니다. 스크린샷 2020-05-01 오후 7 26 29

위에서 설명한 간단한 시각적인 접근성 테스트 말고도, 이 addon을 사용하면 다양하게 접근성에 위배되는 사항들에 대해 테스트를 해볼수 있게 됩니다.

스크린샷 2020-05-01 오후 7 47 09


🛠 Customize 관련

위와 같이 addon을 추가하는것 이외에도 다양하게 storybook을 custom 하는 방법들이 있는데요, 그 중 몇가지를 소개하면 아래와 같습니다.

스토리 hierarchy 설정하기

프로젝트의 구조를 잡듯이, storybook 내에서도 story들의 구조를 잡는 방법도 있습니다.

[folder 구조잡기]

/ 를 사용해 폴더를 명시해줄수 있고, /를 계속 추가해주면 folder역시 계속 생기게 되어, 폴더구조를 정리할수 있습니다.

export default {
  title: "atoms/Button",
  component: Button,
};

[root 이름 노출]

| 앞에 root에 해당하는 네이밍을 적어주면 됩니다.

export default {
  title: "DesignSystem|atoms/Button",
  component: Button,
};

스크린샷 2020-05-01 오후 5 47 16

Storybook custom UI 테마 설정하기

회사 내에서 혹은 사이드프로젝트 등에서도 storybook을 자주 활용하게 되는데, 프로젝트 성격에 맞게 storybook의 테마를 꾸밀수 있습니다.

기본제공 테마 사용

//.storybook/preview.js
import { addParameters } from "@storybook/react";
import { themes } from "@storybook/theming";

addParameters({
  options: {
    theme: themes.dark,
  },
});

직접 theme 만들어 사용

//yourTheme
import { create } from "@storybook/theming/create";

export default create({
  base: "light",

  colorPrimary: "hotpink",
  colorSecondary: "deepskyblue",

  // UI
  appBg: "white",
  appContentBg: "silver",
  appBorderColor: "grey",
  appBorderRadius: 4,

  // Typography
  fontBase: '"Open Sans", sans-serif',
  fontCode: "monospace",

  // Text colors
  textColor: "black",
  textInverseColor: "rgba(255,255,255,0.9)",

  // Toolbar default and active colors
  barTextColor: "silver",
  barSelectedColor: "black",
  barBg: "hotpink",

  // Form colors
  inputBg: "white",
  inputBorder: "silver",
  inputTextColor: "black",
  inputBorderRadius: 4,

  brandTitle: "My custom storybook",
  brandUrl: "https://example.com",
  brandImage: "https://placehold.it/350x150",
});

//.storybook/preview.js
import { addons } from "@storybook/addons";
import yourTheme from "./yourTheme";

addons.setConfig({
  theme: yourTheme,
});

Etc

위에서 설명한것 이외에도 storybook을 활용할 수 있는 방법은 무궁무진 합니다. 다른 좋은 사례들이 있으면 공유해주시면 감사하겠습니다 :)

storybook 사용시 참고하면 좋을 글들

Powered with by Ideveloper