CRA + Redux + styledComponent 로 구성된 프로젝트에 storybook 세팅하기
아래의 내용은 storybook 6.0.22 version을 기준으로 설명하고 있습니다.
npx @storybook/cli sb init
설치를 하고나면 프로젝트 루트 디렉토리에 .storybook 디렉토리와 src디렉토리 하위에 stories라는 디렉토리가 생기고 package.json에 storybook 관련 dependencies, devDependencies, script명령어가 생긴것을 확인할 수 있습니다.
해당하는 디렉토리가 무엇이고 각 파일이 의미하는 것이 무엇인지 확인해보겠습니다.
stories부분은 stroybook에 표현할 컴포넌트들을 정의합니다.
".stories.@js|jsx|ts|tsx"
으로 정의되있기에 src폴더 하위에 .stories가 파일명에 포함되 있으며 확장자가 js/jsx/ts/tsx로 되어있는 파일들을 모두 스토리북에 표현하겠다는 의미입니다.addon 부분은 storybook에 어떤 addon을 추가시킬지 설정하는 부분입니다.
npm install @storybook/addon-a11y --dev
명령어를 통해서 에드온을 설치 및 devDependencies에 추가하고addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/preset-create-react-app",
"@storybook/addon-a11y",
],
preview.js에서는 preview부분과 관련된 설정을 합니다.
이 부분을 이용하여 story에 데코레이터를 추가할 수 있습니다.
데코레이터란 story 컴포넌트가 storybook에 표현될 때 추가적으로 장식으로 들어가는 다른 컴포넌트들이나 Provider들을 추가할 수 있는 것입니다.
Redux나 styled-components를 사용할 경우에는 루트가 되는 스크립트 파일인 index.js에서 Provider를 통해서 store를 전역에 추가해주고, ThemeProvider를 통해서 theme파일을 전역에 추가하는 식으로 세팅을 많이 했을 것입니다.
Provider와 ThemeProvider가 추가된 index.js파일의 예시
storybook은 일반적으로 서버를 구동시킬때 index.js를 통해서 모든 컴포넌트가 Provider를 통해서 Provider를 제공받은 후 보여지는 것이 아니라
개별 컴포넌트가 스토리북에 보여지는 것이므로 저런 Provider가 제공된 상태가 아니기에 theme와 store를 사용하였을 경우에 에러가 발생하거나 원하는대로 동작하지 않습니다.
따라서 Decorator를 통해서 Provider를 개별 스토리에 다 제공해줘서 store와 theme을 제공받도록 해아합니다.
개별 스토리마다 decorator를 추가할 수도 있지만, 모든 스토리에 공통적으로 적용되어야 하는 decorator라면 Preview.js에 전체적으로 데코레이터를 추가해주는 방식이 간편합니다.
Preview.js 파일의 예시
위 preview.js파일을 보면 index.js에 Provider를 제공한것과 동일하지만 중간에 Story라는 컴포넌트가 들어가 있는 것을 볼 수 있습니다.
정확한 내용은 공식문서에서 해당하는 내용을 찾아봐야겠지만 제가 사용하고 세팅을 하면서 추측하기로는 decorator는 story라는 인자를 받는데 이 인자는 각 .stories파일들에서 export하는 컴포넌트들이고 그 Story파일에 데코레이터로 Provider, ThemeProvider, GlobalStyles를 감싸준 다음에 렌더시키는 방식으로 보입니다.
제 경우에는 모바일 사이즈를 개발하고 잇기에 width:360px을 가진 wrapper를 전체적으로 적용시켜준 모습을 볼 수 있습니다.
이 개념을 이해하면 이제 스토리북에 다양한 데코레이터를 추가해서 여러가지 기본적인 설정을 해줄 수 있습니다.
Storybook에는 사용자를 위해서 docs를 추가할 수 있습니다.
mdx파일을 추가하는 방식과 PropTypes를 통해서 간단하게 표현해줄 수 있는 방법이 있습니다.
저의 경우에는 propTypes를 통해서 간략하게 문서화 하는 식으로 진행하였습니다.
React에서 기본적으로 제공하는 prop-types 라이브러리를 통해서 Props의 타입을 명시할 수 있고, 이와 주석을 결합하여 간략하게 해당하는 prop의 documentation을 스토리북에 포함할 수 있습니다.
Example.js 파일
---
import React from "react";
import styled from "styled-components";
function Example({ color }) {
return <Container>Example</Container>;
}
export default Example;
const Container = styled.p`
width: 200px;
color: blue;
font-size: 36px;
`;
Example.stories.js 파일
---
import React from "react";
import Example from "./Example";
export default {
title: "Components",
componenet: Example,
};
export const Default = () => <Example />;
위와 같은 형식으로 하나의 컴포넌트파일을 만들고 .stories.js파일을 만들어서 storybook에 컴포넌트를 표현할 수 있습니다.
실제 스토리북에 들어가보면 컴포넌트의 모습은 보이지만 문서화가 되지 않아 사람들이 알아보기 어려운 것을 알 수 있습니다.
import React from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
function Example({ color }) {
return <Container color={color}>Example</Container>;
}
Example.defaultProps = {
color: "black",
};
Example.propTypes = {
/** 글자의 색을 지정하는 Props */
color: PropTypes.string,
};
export default Example;
const Container = styled.p`
width: 200px;
color: ${({ color }) => color};
font-size: 36px;
`;
위와 같이 propTypes를 통해서 defaultProps와 propTypes를 지정해주면 해당하는 주석을 문서로 출력해줍니다.
position:fixed, bottom:0
이 설정되어있는 컴포넌트가 있을 경우에 docs페이지에서 docs페이지 전체의 bottom에 모든 컴포넌트가 위치해버리는 이슈가 있습니다.import React from 'react'
import Example from "./Example";
export default {
title:"Test",
component:Example,
parameters: {
docs: {
inlineStories: false,
story: {
ifameHeight: 500,
},
},
},
}
export const Default = (args) => <Example {...args} />
export const Blue = () => <Example color="blue" />
잘봤습니다.
previews 에 store 를 넣어야 한다는걸
이 포스트를 보고 알았네요..
제 삽질시간을 조금 단축시켜주셔서 감사합니다