스토리북(Storybook)의 기본 구성 단위는 스토리(Story)이며 하나의 UI 컴포넌트는 보통 하나 이상의 Story를 가지게 됩니다. 각 Story는 해당 UI 컴포넌트가 어떻게 사용될 수 있는지를 보여주는 하나의 예시라고 생각하시면 이해가 편하실 것 같습니다.
Storybook을 사용하면 UI 컴포넌트가 각각 독립적으로 어떻게 실제로 랜더링되는지 직접 시각적으로 테스트하면서 개발을 진행할 수 있습니다. 해당 UI 라이브러리를 사용하는 개발자 입장에서도 코드를 보지 않고도 미리 각 UI 컴포넌트를 체험해보고 사용할 수 있어서 매우 유용합니다.
스토리북 공식 홈페이지를 보니 다양한 프레임워크&라이브러리에서도 사용이 가능하다.
찾아보던 중 Chormatic
이라고, 작성한 스토리북을 배포할 수 있는 플랫폼도 있다고 한다.
npx @storybook/cli sb init
npm run storybook
해당 명령어로 Storybook 서버는 각 Story가 실제 브라우저에서 어떻게 랜더링되는지 확인할 수 있는 컴포넌트 라이브러리 익스플로러를 제공한다.
Storybook 서버는 프로젝트와는 별도로 제공되는 서버다. Storybook 서버가 아닌 실제 프로젝트를 기동시키려면 루트 디렉터리에 다음과 같이 .env 파일을 생성할 필요가 있다.
SKIP_PREFLIGHT_CHECK=true
storybook을 설치하면 가장 상단에 .storybook
이라는 폴더가 생성된다.
기본적으로 main.js
, preview.js
두가지 파일이 들어있다.
외에 프로젝트 src안에서 컴포넌트와 스토리 파일을 작성하면된다.
Storybook-project/
├── src/
│ └── components/
│ ├── ...
│ ├── Text.jss # => 📚Component
│ ├── Text.story.js # => 💞Story
│ └── ...
먼저 간단한 리액트 컴포넌트를 작성해보자.
Text컴포넌트는 넘어온 color, italic, underline에 따라 각기 다른 스타일이 적용된 children프롭을 렌더링한다.
Text.jsx
import PropTypes from 'prop-types';
// ui 컴포넌트로 넘어온 color, italic, underline에 따라
// 각기 다른 스타일이 적용된 children프롭을 렌더링
export function Text({ children, color, italic, underline }) {
const style = {
color: color,
fontStyle: italic ? 'italic' : 'normal',
textDecoration: underline ? 'underline' : 'none',
};
return <span style={style}> {children}</span>;
}
Text.propTypes = {
children: PropTypes.string.isRequired,
color: PropTypes.string,
italic: PropTypes.bool,
underline: PropTypes.bool,
};
Text.defaultProps = {
color: 'black',
italic: false,
underline: false,
};
.stores.js
라는 확장자의 파일은 스토리를 적는 파일이다.
반드시 1개 이상의 스토리를 export 해야 한다.
조금 어렵게 보일수도 있겠지만, 이 파일은 Text컴포넌트를 어떻게 사용할 수 있는지를 알려준다고 생각하면 된다.
import { Text } from './Text.jsx';
// UI컴포넌트에 대한 메타 정보
export default { // 여기에서 설정하면 stories.tsx 범위
title: 'component/text', // 사이드바에 보여질 이름
component: Text,
tags: ['autodocs'], // 자동 docs 생성
parameters: {
layout: 'centered', // 컴포넌트 중앙 배치
backgrounds: { // storybook에서 적용가능한 색상
values: [
{ name: 'black', value: '#000000' },
{ name: 'green', value: '#0f0' },
],
},
},
};
const STORY_TEXT = 'my first learning of story book';
// 1. 컴포넌트의 활용 예시를 나타내는 Story를 함수 형태로 작성한다.
export const Default = () => <Text>{STORY_TEXT}</Text>;
export const Red = () => <Text color="red">{STORY_TEXT}</Text>;
export const Italic = () => <Text italic>{STORY_TEXT}</Text>;
export const Underline = () => <Text underline>{STORY_TEXT}</Text>;
// 혹은
// 아래처럼 더 편하게 작성할수도 잇다.
// 2-1 .Template으로 기본 포맷을 정해두고
const Template = (args) => <Text {...args}>{STORY_TEXT}</Text>;
// 2-2. bind로 제어한다.
export const Blue = Template.bind({});
Blue.args = {
color: 'blue',
};
Blue.storyName = 'my blue text';
// 위 코드는 아래와 동일
// export const Blue = () => <Text color="blue">{STORY_TEXT}</Text>
export default {}
해당 UI 컴포넌트에 대한 메타 정보를 객체로 작성하는데
title
은 Storybook 메뉴 사이드바에서 표시될 이름을 지정한다.
component
에는 위에서 작성한 React 컴포넌트를 지정한다.tags
: [’autodocs’]
옵션을 주면 자동으로 doc을 생성해준다.