참고:
스토리북 == 비주얼테스터
컴포넌트/UI를 상태별로 확인 할 수 있는 라이브러리로 react뿐만아닌 다른 프레임워크에서도 지원된다!
이런거 굳이 알아야 되나? 했지만 막상 간단한 실습만으로도 왜 쓰는지 알 것 같다.
컴포넌트 수정할 때마다 UI가 정삭 작동 하는지 서버켜고 확인하고 코드 수정하고 반복.. 하지않고,
먼저 스토리북에서 props 설정에 따라 반영된 UI를 나열해두고 볼수있고, (일단 여기까지만 실습해봤다)
협업할 때도 공유해서 보기좋은 듯! 나도 보기 좋고!
스토리북 장점
- UI 컴포넌트의 다양한 예시를 보여줄 수 있다.
- 다수의 프론트엔드 개발자가 참여한다면 코드이해, 커뮤니케이션에 들이는 비용을 낮춰준다.
- 다양한 확장도구(addon) 지원 & 직접 구현 가능
npm i -D @storybook/react
"scripts": {
"storybook": "start-storybook -p 9001 -c .storybook",
...
}
스토리북 시작을 위한 스크립트를 추가한다.
src/stories/파일명.js
: 스토리 파일을 만든다./.storybook/config.js
: 루트에 .storybook
안에 설정파일 config.js
를 생성하여, 스토리파일을 불러들인다.// inputStory.js
import React from 'react';
import { storiesOf } from '@storybook/react'; // 스토리북 모듈 가져오기
// 추가할 컴포넌트 가져오기
import Input1 from '../components/Input1';
import Input2 from '../components/Input2';
import Button1 from '../components/Button1';
import Button2 from '../components/Button2';
// storiesOf('스토리북에 표시할 스토리이름', module).add('스토리북에 표시할 메뉴이름',()=><해당 컴포넌트 />>)
storiesOf('Input', module)
.add('기본인풋', () => <Input1 />)
.add('블랙모드', () => <Input2 />);
// 버튼 UI도 여기에 포함시켰는데.
// ButtonStory.js를 만들고 config.js에서 스토리북에 추가시키길 추전
storiesOf('Button', module)
.add('기본버튼', () => <Button1 />)
.add('블랙모드', () => <Button2 />);
스토리 파일은 src/stories
폴더에 위치시킨다.
storiesOf('좌측-대메뉴', module)
: 스토리를 생성한다. .add('좌측-소메뉴', ()=> <추가컴포넌트명/>)
: 컴포넌트를 CB으로 전달한다.// .storybook/config.js
import { configure } from '@storybook/react';
function loadStories() {
// 여기에 스토리파일을 추가 할 수 있다.
require('../src/stories/InputStory');
}
configure(loadStories, module);
// src/stories/InputStory.js
...중략
storiesOf('Input', module)
.add('기본인풋', () => <Input value='기본인풋' />)
.add('블랙모드', () => <Input value='블랙모드' color='dark' />);
UI의 모습을 props에 따라 다르게 반응하도록 설정
하고 스토리북 서버에서 해당 UI를 확인할 수 있다.
협업에도 도움되고, 나도 보기 좋고~!
Input
, Button
등 종류단위로 UI 구분src/stories
경로에 위치한다.위 예제에서 InputStory.js
에 Button
과 Input
을 모두 함께 등록하였다. UI 종류 단위로 스토리를 정리하기위해 분리해보자
stories/InputStory.js
: input
UI만 담는다stories/ButtonStory.js
: Button
UI만 담는다.storybook/config.js
: InputStory
, ButtonStory
를 require()
한다.config.js
를 수정해 ...Story.js
로 끝나는 파일을 자동등록 하도록 설정해보자.
import { configure } from '@storybook/react';
// ...Story.js 자동 등록을 위한 모듈
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
function loadStories() {
// + 하나씩 추가하는 법
// require('../src/stories/InputStory');
// + 자동 추가하는 법
const context = require.context(
'../src/stories',
true,
/Story\.js$/ || /Story\.jsx$/ // js or jsx
);
context.keys().forEach((srcFile) => {
interopRequireDefault(context(srcFile));
});
}
configure(loadStories, module);
스토리북 서버를 재부팅 하면 config.js를 수정하지 않아도 추가로 Story가 추가된다.
참고 : require.context()
addon-actions
: 이벤트 작동 테스트를 위한 확장도구addon-jsx
: 컴포넌트 사용 코드를 출력을 위한 확장도구npm i -D @storybook/addons @storybook/addon-actions
npm i -D storybook-addon-jsx
설정파일에
import '확장도구들'
해주지 않으면 백날.. 코드 두드려봐야 스토리북 서버에 확장도구 패널이 나타나질 않는다!
.storybook/addons.js
파일에 import
모듈
// .storybook/addons.js
// 스토리북 확장도구(addon)은 이곳에 추가
import '@storybook/addon-actions/register'
import 'storybook-addon-jsx/register'
확장도구는 src/stories/...Story.js(x)
파일에 적용할 수 있다.
사용전에 2)설정 먼저 진행하는 거 잊지말기!
// inputStory.js
import React from 'react';
import { storiesOf } from '@storybook/react'; // 스토리북 모듈 가져오기
// addon 추가
import { action } from '@storybook/addon-actions';
// 컴포넌트 추가
import Input from '../components/Input'; // 추가할 컴포넌트 가져오기
storiesOf('Input', module)
.add('기본인풋', () => <Input value='기본인풋' />)
.add('블랙모드', () => <Input value='블랙모드' color='dark' />)
.add('onChange예제', () => (
<Input onChange={action('onChange 이벤트 발생')} />
)); // action()을 사용
사용전에 2)설정 먼저 진행하는 거 잊지말기!
addon-jsx
를 사용하기 위해서는 스토리북 설정파일 .storybook/config.js
와 적용할 스토리파일(...Story.js
)을 수정해야 한다.
// .storybook/config.js 수정
import { configure } from '@storybook/react';
import interopRequireDefault from 'babel-runtime/helpers/interopRequireDefault';
// addon-jsx를 위한 추가 import
import {setAddon} from '@storybook/react';
import JSXAddon from 'storybook-addon-jsx';
function loadStories() {
const context = require.context(
'../src/stories',
true,
/Story\.js$/ || /Story\.jsx$/
);
context.keys().forEach((srcFile) => {
interopRequireDefault(context(srcFile));
});
}
setAddon(JSXAddon) // setAddon 함수호출
configure(loadStories, module);
전체를 보면 좀 길어보이지만 이전 자동 스토리 추가하기 코드에서 딱 3줄 추가되었다.
import {setAddon} from '@storybook/react';
import JSXAddon from 'storybook-addon-jsx';
setAddon(JSXAddon)
// src/stories/...Story.js 스토리 파일들 수정
...생략
storiesOf('Input', module)
.addWithJSX('기본인풋', () => <Input value='기본인풋' />)
.addWithJSX('블랙모드', () => <Input value='블랙모드' color='dark' />)
.addWithJSX('onChange예제', () => (
<Input
onChange={action('이벤트 반응!', (e) => console.log(e.target.value))}
/>
));
add()
함수를 addWithJSX()
로 변경한다. 이후 스토리북 서버 재부팅 하고 확인한다.프로젝트의 style을 sass로 진행중이라면 스토리북에서는 sass가 적용되지 않고 보일 것이다.
스토리북을 위해 sass-loader
패키지 설치와 webpack.config.js
설정이 필요하다.
npm i -D sass-loader
: 스토리북 웹팩 설정을 위해 설치.storybook/webpack.config.js
: 스토리북 폴더에 웹팩 설정을 추가// .storybook/webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.scss$/,
loaders: ['sass-loader'],
include: path.resolve(__dirname, '../'),
},
],
},
};
...Story.js
파일에서 적용할 stylesheet
파일 import
// src/stories/...Story.js
// 적용할 스타일 추가
import '../sass/materialize.scss';
npm i styled-components
패키지 설치 후 하던대로 작성하고 사용하면 됨!