team logo icon
article content thumbnail

StoryBook의 기본 개념에 대하여

StoryBook의 기본 개념을 살펴보았습니다.

Storybook이란?

React, Angular, Vue 등의 분리된 UI 컴포넌트를 체계적이고 효율적으로 구축할 수 있는 UI 컴포넌트 개발 도구다. UI 컴포넌트 라이브러리의 문서화(documentation)를 위해 사용할 수도 있고 디자인 시스템(Design system)을 개발하기 위한 플랫폼으로 사용할 수도 있다.

스토리북의 기본 구성 단위 = 스토리(Story) 👉 하나의 UI 컴포넌트는 보통 하나 이상의 Story를 가지게 된다. 👉 각 Story는 해당 UI 컴포넌트가 어떻게 사용될 수 있는지를 보여주는 하나의 예시!

스토리북을 사용하면 UI 컴포넌트가 각각 독립적으로 어떻게 실제로 랜더링되는지 직접 시각적으로 테스트하면서 개발을 진행할 수 있다. 해당 UI 라이브러리를 사용하는 개발자 입장에서도 코드를 보지 않고도 미리 각 UI 컴포넌트를 체험해보고 사용할 수 있어서 매우 유용하다.

특히 Mockup 상태를 넣어줄 수 있어 상태 값에 따라 변경되는 디자인을 바로 확인할 수 있다.

그래서 왜 사용하는데?

컴포넌트 기반 개발

  • 기존에 스타일 작업을 할 때는 여러 상태에 따라 달라지는 컴포넌트들을 매번 확인하기 번거로웠다! 이 불편함을 해결해준다 ex) 로그인을 한 상태에서만 보이는 아이콘, 로딩중일 때, hover했을 때, focus했을 때, input값이 유효할 때 등등 ..

  • 다른 사람의 코드를 이해하는데 드는 노력을 줄일 수 있다.

  • 자연스럽게 컴포넌트 단위로 생각하면서 개발을 진행할 수 있다.

  • 독립적인 환경에서의 UI 컴포넌트 개발 (개발하는 웹과 따로 서버를 킬 수 있기 때문!)

  • 컴포넌트 재사용 ⬆

참고 : Storybook은 UI 컴포넌트를 위한 놀이터 이 자료에서 특히 UI 컴포넌트를 위한 놀이터 부분을 읽어보면 아! 이래서 스토리북 쓰는구나 하고 확 체감이 되는 것 같다. 그래서 읽어보기를 추천한다!!

Storybook 설치

▶ 설치

yarn add global @storybook/cli
npx sb init // 필요한 의존성을 자동 설치해주고, package.json에 scripts 실행 및 빌드 명령어도 추가해준다.

🔽 선택 : 스토리북을 실행했을 때 컴포넌트 테이블을 만들어줌. 컴포넌트의 props, type, 주석 등이 적혀 있어서 개발할 때 아주 유용함.

yarn add --dev react-docgen-typescript-loader 

▶ 실행

yarn storybook // 6006 포트

Storybook 폴더구조

각 파일이 뭘 하는지 알아보자!

  • .storybook : Storybook 설정 파일들

  • .storybook/main.ts : stories를 위한 config 설정, 스토리북 자체의 구성 파일 (addon도 여기서 관리!)

import type { StorybookConfig } from "@storybook/react-vite";
const config: StorybookConfig = {
  stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
  ],
  framework: {
    name: "@storybook/react-vite",
    options: {},
  },
  docs: {
    autodocs: "tag",
  },
};
export default config;

addon Storybook의 plugin 시스템. 공식 지원 addon 외에도 여러 오픈소스 addon을 register하여 기본 기능에 추가 기능을 붙일 수 있다. 반응형 개발을 위한 Viewport도 있으며, 라우팅을 위한 react-router도 존재한다. 아래서 다룰 args의 변화로 실시간으로 컴포넌트를 수정하는 것은 공식적으로 storybook에서 지원하는 기본 contorls addon이다!

  • .storybook/preview.ts : 모든 story들에 글로벌하게 적용될 포맷 세팅, 사용자가 작성하는 스토리의 구성 파일 (ex. GlobalStyle, ThemeProvider ...)

import type { Preview } from "@storybook/react";

const preview: Preview = {
  parameters: {
    actions: { argTypesRegex: "^on[A-Z].*" },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
};

export default preview;

  • src/stories : Storybook 예제 컴포넌트들

Story 작성하기

기본꼴

<컴포넌트이름>.stories.js

export default {
  title: //스토리북에 올릴 component폴더 계층 구조,
  component: // 스토리를 만들 컴포넌트 이름
}

export const 스토리이름 = () => 해당스토리에서 테스트할 인자가 담긴 컴포넌트

속성

title : 스토리북에 올릴 component 폴더 계층 구조

  • ex) title: 'Example/Button은 Example 그룹의 Button 스토리

component : 스토리를 만들 컴포넌트 이름 args : 모든 스토리에 공통으로 전달될 props. argTypes : 각 Story args의 행동 방식 설정.

  • ex) backgroundColor: {control: 'color'} => controls에서 선택한 컬러를 컴포넌트의 props로 전달하겠다는 의미

    controls 개발자가 코드를 따로 변경하지 않고 Storybook에서 arguments를 동적으로 바꿔가며 인터렉션할 수 있도록 도와주는 기능 (ex. color, 텍스트 등 바꿔보기)

decorators : Story를 감싸 추가적인 렌더링 가능한 기능 parameters : Story에 대한 정적 메타 데이터 정의 excludeStories : 렌더링 제외 설정 actions : 클릭이 될 때 Storybook UI의 actions 패널에 나타날 콜백을 생성함으로써 버튼 클릭이 성공적이었는지 테스트 UI에서 확인할 수 있다.

이 외 참고 : How to write stories

예제

버튼을 만들어보자 📑 Input.tsx 먼저 대부분이 잘 알고 있는 리액트 컴포넌트를 만드는 것과 똑같다.

import React from 'react';
import { string, bool } from 'prop-types';
import './Input.css';

const Input = React.forwardRef(function Input(
  { id, label, placeholder, readonly, disabled, error, ...others },
  ref
) {
  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <input
        id={id}
        type='text'
        placeholder={placeholder}
        readOnly={readonly}
        disabled={disabled}
        {...others}
        ref={ref}
      />
      {error && <div class='error'>{error}</div>}
    </div>
  );
});

export default Input;

Input.propTypes = {
  /** 아이디* */
  id: string.isRequired,
  /** 레이블* */
  label: string.isRequired,
  /** 플레이스홀더 */
  placeholder: string,
  /** 읽기전용 상태 */
  readonly: bool,
  /** 비활성 상태 */
  disabled: bool,
  /** 에러 메시지 */
  error: string
};

📑 Input.css 위에서 import한 css 파일이다.

label {
  display: inline-block;
  margin-bottom: 0.5rem;
}

input {
  display: block;
  width: 100%;
  padding: 0.375rem 0.75rem;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
  color: #212529;
  background-color: #fff;
  background-clip: padding-box;
  border: 1px solid #ced4da;
  appearance: none;
  border-radius: 0.25rem;
  transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.error {
  margin-top: 5px;
  font-size: 15px;
  color: #e52528;
}

📑 Input.stories.jsx 스토리를 작성해보면,

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

export default {
  title: 'components/Form/Input',
  component: Input
};

// 기본 포맷
const Template = args => <Input {...args} />;

// bind로 제어
// 이 아래 각각이 새로운 스토리들인 것!
export const Password = Template.bind({});
Password.args = {
  id: 'password',
  label: '패스워드',
  type: 'password',
  value: '1234',
  placeholder: '패스워드를 입력하세요.'
};
Password.storyName = 'Password';

export const UserIdError = Template.bind({});
UserIdError.args = {
  id: 'userid',
  label: '아이디',
  value: 'user@email.',
  placeholder: '아이디로 사용할 이메일을 입력하세요.',
  error: '아이디(이메일)는 이메일 형식으로 입력해주세요.'
};
UserIdError.storyName = 'Password(Error)';

export const Large = {
  args: {
    size: 'large',
    label: 'Button',
  },
};

export const Small = {
  args: {
    size: 'small',
    label: 'Button',
  },
};

그 결과! 아래처럼 Story들이 생겨난다 Password Password(Error)

이렇게나 편하게 여러가지 UI에 대한 테스트가 가능하다니.. 너무 멋지다!!

단점

그러나 많은 것을 고려하면서 개발을 하다보니 개발의 속도도 느려지고, 스토리북이라는 새로운 툴을 도입함으로써 세팅과 이슈를 해결하는데 시간을 더 투자하게 된다. 그래서! 토이 프로젝트나 규모가 작은 프로젝트의 경우에는 이점이 별로 없다고 할 수 있겠다.

참고자료 공식 웹사이트 kakao FE 기술블로그 - 스토리북 작성을 통해 얻게 되는 리팩토링 효과

최신 아티클
palms.blog 팀원 초대해서 팀블로그로 사용하기
김대덕
|
2024.06.05
palms.blog 팀원 초대해서 팀블로그로 사용하기
팀원 초대해서 팀블로그 만드는 방법과 각 팀원 권한에 대한 설명
Article Thumbnail
김대덕
|
2024.01.13
팜스프링팀에게 보내는 글 (23.07.02)
합숙이 시작되기도 전, 새벽 감성에 젖어 팀원들에게 보냈던 슬랙 메시지
Article Thumbnail
김서현
|
2024.01.09
장명지와 김서현의 10시간의 릴리즈 대장정
장명지와 김서현의 10시간 릴리즈 대장정에 대한 후기, 그리고 팀 팜스프링...