본문 바로가기

Web.d

[Storybook][React] Storybook 기초 적용해보기

반응형
  1. 간단 설명
  2. 초기 세팅
  3. Story 작성하기
  4. Addons
  5. 마무리

1. 간단 설명

Storybook은 개발 모드에서 실행된다

비즈니스 로직과 Context로부터 UI 컴포넌트를 독립적으로 분리하여 만들 수 있도록 도와준다

React 이외의 React NativeVueAngular 그리고 Svelte에 대한 문서도 있다고 하니 참고하자

하위 컴포넌트 → 페이지 로 개발하는 컴포넌트 기반 개발(Component-Driven Development)  (CDD) 방법론에 따라 UI를 만드는 것이 기본이다

 

2. 초기 세팅

 

// Add Storybook 및 Jest 테스트 환경
npx -p @storybook/cli sb init

// story북 실행했을 때 컴포넌트 테이블 만들기 위해 설치
yarn add --dev react-docgen-typescript-loader

 

// Run the test runner (Jest) in a terminal:
yarn test --watchAll

// Start the component explorer on port 6006:
yarn storybook

// Run the frontend app proper on port 3000:
yarn start

 

.storybook/main.js

 

module.exports = {
  //👇 Location of our stories
  stories: ["../src/**/*.stories.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
    "@storybook/preset-create-react-app",
  ],
  framework: "@storybook/react",
  core: {
    builder: "@storybook/builder-webpack5",
  },
};

 

.storybook/preview.js

 

// import "../src/index.css"; //👈 The app's CSS file goes here
import { GlobalStyle } from "../src/index";

export const parameters = {
  // Action 탭에서 이벤트가 발생하는 것을 감지
  //👇 Configures Storybook to log the actions( on 으로 시작하는 이벤트 핸들러 함수 ) in the UI.
  actions: { argTypesRegex: "^on[A-Z].*" },
  // controls - 개발자가 코드를 수정하지 않아도 storybook에서 동적으로 인터렉션 가능하도록
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

// 추가::styled-components의 ThemeProvider 통해
export const decorators = [
  (Story, context) => (
    <>
      <GlobalStyle />
      <Story {...context} />
    </>
  ),
];

 

3. Story 작성하기

 

title 스토리북 폴더 계층 구조 제목
component 렌더링 할 컴포넌트 (addon을 위해 써주는 것이 권장됨)
args story의 props 이자 input
decorators story를 래핑하는 추가 렌더링 기능
parameters story에 대한 정적인 메타데이터 정의,
주로 storybook의 기능과 addon을 조작
actions 클릭이 될 때 Storybook UI의 actions 패널에 나타날 콜백을 생성함으로써 
버튼 클릭이 성공적이었는지 테스트 UI에서 확인할 수 있다

 

 

src/stories/MyComponent.tsx

 

import styled from "styled-components";

export interface MyComponentProps {
  name: string;
  phoneNumber: string;
  distance: string;
  address: string;
}

export default function MyComponent(props: MyComponentProps) {
  const { name, phoneNumber, distance, address } = props;

  return (
    <StCardWrapper>
      <StName>{name}</StName>
      <StInfoWrapper>
        <StPhoneNumber>{phoneNumber ? phoneNumber : "❌"}</StPhoneNumber>
        <StDetail>{distance ? distance + "미터" : address}</StDetail>
      </StInfoWrapper>
    </StCardWrapper>
  );
}

const StCardWrapper = styled.article`
  width: 90%;
  height: 4rem;

  margin-top: 1rem;

  border-radius: 1rem;

  background-color: #e0e0e0;
`;

const StName = styled.strong`
  display: inline-block;

  margin: 0.5rem 0 0 0.5rem;

  font-weight: 600;
`;

const StInfoWrapper = styled.div`
  display: flex;
  justify-content: space-between;

  margin: 0.5rem;
`;

const StPhoneNumber = styled.p`
  padding: 0.1rem;

  border-radius: 1rem;
  border: 0.1rem solid #333333;

  background-color: orange;
`;

const StDetail = styled.p`
  width: 50%;

  font-size: 0.8rem;

  text-align: right;
`;

 

src/stories/MyComponent.stories.tsx

 

import { Meta, Story } from "@storybook/react";

import MyComponent, { MyComponentProps } from "./MyComponent";

// 스토리북의 폴더
export default {
  title: "Example/MyComponent",
  component: MyComponent,
  decorators: [
    (Story: () => JSX.Element) => (
      <div style={{ margin: "3em" }}>
        <Story />
      </div>
    ),
  ],
} as Meta;

// Story Template 정의
const Template: Story<MyComponentProps> = (args) => {
  return <MyComponent {...args} />;
};

// Story1 정의
export const MyComponentStory1 = Template.bind({});
MyComponentStory1.args = {
  name: "",
  phoneNumber: "",
  distance: "",
  address: "",
};

// MyComponentStory1.decorators = [(Story) => <div style={{ margin: '3em' }}><Story/></div>];

MyComponentStory1.parameters = {
  backgrounds: {
    values: [
      { name: "lightBlue", value: "lightBlue" },
      { name: "gray", value: "#eeeeee" },
    ],
  },
};

MyComponentStory1.storyName = "Custom";

 

4. Addons

Storybook에는 addon 이라는 plugin 시스템이 있다

공식적으로 지원하는 addon 뿐만 아니라 여러 오픈소스 addon도 존재한다는 것!

여러가지 addon을 register하여 Storybook의 기본 기능에 추가 기능을 붙일 수 있다

 

Parameters에서 잠깐 소개했던 Background와 Action도 이에 해당하고,

args 변화로 실시간으로 컴포넌트를 수정하는 것도 contorls addon이고,

반응형 개발을 위한 Viewport도 있으며,

라우팅을 위한 react-router도 존재한다고 하니, 찾아보는 것도 좋을 것 같다

(next.js router도 물론 오픈소스로 개발되어 있다)

 

5. 마무리

이 설정, 저 설정 때문에 꽤나 애먹었다

절대 경로 설정은 너무 복잡하고 번거롭다는 거,, 알아주셨으면 한다,,,

 

하지만 아무래도 하위 컴포넌트를 개발하고,

이들을 조립하며 페이지를 개발하는 순서를 따르게 된다는 점이 중요하고 매력적이다

 

스토리북을 사용하는 이들에게 자문을 구한 결과,

외부에 종속적인 (예를 들어 API 요청을 하는) 컴포넌트들을 제외한

독립적으로 동작할 수 있는, 컴포넌트들에 대해 스토리를 정의해주며 개발한다고 한다

 

이를 통해 협업 과정에서 특별한 conflict 없이 독립적인 환경에서 컴포넌트를 개발할 수 있고,

이들을 유용하게 QA, 테스트 할 수 있다!

협업을 하다가 같은 스타일링에 대해서 중복적으로 개발하는 경험도 줄일 수 있을 것 같다

 

이 외에도 데이터를 연결하거나 등의 기능이 다양한데,

기본적으로 위의 내용들로 작성이 가능할 것이라고 생각하고,

후에 좋은 내용이 있다면 더 추가하도록 하자

 


[Storybook] Storybook 200% 활용하기

 

[Storybook] Storybook 200% 활용하기

🙌 들어가기 회사에 들어온 뒤 온보딩 과제를 끝내자마자, 첫 세미나를 맡게 되었습니다 🎉 이번 200% 시리즈는 Storybook 입니다!

velog.io

https://storybook.js.org/tutorials/intro-to-storybook/react/ko/get-started/

 

React를 위한 Storybook 튜토리얼

Storybook을 개발 환경에 설치해봅시다

storybook.js.org

Teamble-Web/Header.stories.tsx at main · Team-Teamble/Teamble-Web

 

GitHub - Team-Teamble/Teamble-Web: 💙💙러블리한 웹 팀블러💙💙

💙💙러블리한 웹 팀블러💙💙. Contribute to Team-Teamble/Teamble-Web development by creating an account on GitHub.

github.com

스토리북 제대로 활용하기

 

스토리북 제대로 활용하기

스토리북 제대로 활용해보기

velog.io

 

반응형