-
728x90
https://storybook.js.org/docs/get-started/install#run-the-setup-wizard
Install Storybook • Storybook docs
Storybook is a frontend workshop for building UI components and pages in isolation. Thousands of teams use it for UI development, testing, and documentation. It’s open source and free.
storybook.js.org
스토리북을 도입하는 이유는 다양하지만 제게 가장 큰 이유는 이렇게 두가지였습니다.
1. 컴포넌트의 문서화를 통한 재사용성 증대
2. 컴포넌트에 props를 다양하게 적용시킨 UI를 자동으로 시각화시켜줌으로인한 테스트와 협업의 용이함
디자이너와의 협업에서도 도움이 되겠지만 제가 느낀 장점은 프론트엔드 개발자끼리의 협업에서 서로가 만든 컴포넌트를 더 잘 이해할 수 있다는 것이었습니다.
사실 서로의 컴포넌트를 공유하며 사용하긴하지만 잘 이해가 안가는 부분이 있거나 추가해야할 props가 생기면 컴포넌트의 복잡도를 높이지 않기 위해, 그리고 길어지는 커뮤니케이션을 피하기 위해 그냥 새로 만들어서 쓰곤했지요!
스토리북이 서로의 컴포넌트에대한 이해를 높여주기 때문에 그런 점들을 해결해줍니다.
(어떤 argument가 왜 필요한지, 직관적으로 어떤 작용을 하는지 보여주기 때문입니다.)
npx -p @storybook/cli sb init --type react_scripts
yarn add storybook@latest yarn add storybook-react-router
yarn storybook init
프로젝트 내에서 세개의 명령어를 실행하면 port 6006으로 실행됩니다.
src 디렉토리에 stories 폴더는 사용 예제들이 담겨있는 폴더이므로 삭제해도됩니다.
중요한 추가 설정!
.storybook/preview.ts
import "../src/app/globals.css";
해당 Import를 추가해야 스토리북에서도 global style이 적용되어 실제 프로젝트와 동일한 UI를 볼 수 있습니다.
.storybook/main.ts
stories: [ "../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)", "../**/*.stories.mdx", "../**/*.stories.@(js|jsx|ts|tsx)", ],
어떤 위치에서든 .stories.tsx 형식의 파일이 생성되면 스토리북에서 인식하도록 위와같이 수정해줘야합니다.
또한, 절대경로를 사용하는 경우 아래의 설정이 꼭 필요합니다.
storybook에서 tsconfig-paths-webpack-plugins 을 함께 사용할 때는 절대 경로를 제대로 가져오지 못해 ‘Module not found’ 에러가 발생합니다.
그래서 해당 플러그인의 옵션으로 tsconfig.json을 직접 경로를 설정해서 가져오게 하면 오류를 해결할 수 있습니다.
https://github.com/storybookjs/storybook/issues/3291#issuecomment-500472928
build-storybook doesn't respect tsconfig.json baseUrl config (Module not found: Error: Can't resolve 'components') · Issue #329
Bug or support request summary I'm honestly not sure if this is a bug or a request for support. Please provide issue details here - What did you expect to happen? What happened instead? I know Type...
github.com
→ dwilhel1 2020.09.04 답변 참고
.storybook/main.ts 를 아래와 같이 수정해주세요.
import type { StorybookConfig } from '@storybook/react-webpack5'; // ================여기부터 추가================== const path = require('path'); const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); // ================여기까지====================== const config: StorybookConfig = { stories: [ '../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)', '../**/*.stories.mdx', '../**/*.stories.@(js|jsx|ts|tsx)', ], addons: ['@storybook/addon-essentials'], framework: { name: '@storybook/react-webpack5', options: { builder: { useSWC: true, }, }, }, docs: { autodocs: 'tag', }, staticDirs: ['../public'], // ================여기부터 추가================== webpackFinal: async (config, { configType }) => { config.module?.rules?.push({ test: /\.scss|.sass$/, use: ['style-loader', 'css-loader', 'sass-loader'], include: path.resolve(__dirname, '../'), }); config.resolve!.plugins = [ new TsconfigPathsPlugin({ configFile: path.resolve(__dirname, '../tsconfig.json'), }), ]; return config; }, // ================여기까지====================== }; export default config;
저는 위 파일 수정 후에 에러가 바로 해결되었는데요, 에러가 사라지지 않는다면 아래 플러그인도 설치해보세요
yarn add --dev tsconfig-paths-webpack-plugin
https://www.npmjs.com/package/tsconfig-paths-webpack-plugin
tsconfig-paths-webpack-plugin
Load modules according to tsconfig paths in webpack.. Latest version: 4.1.0, last published: 6 months ago. Start using tsconfig-paths-webpack-plugin in your project by running `npm i tsconfig-paths-webpack-plugin`. There are 852 other projects in the npm r
www.npmjs.com
추가 설정 끝
아토믹패턴이 적용된 프로젝트의 폴더구조 예시입니다.
components ㄴ atoms ㄴ button ㄴ index.tsx ㄴ molecules ㄴ templates ㄴ pages
컴포넌트와 같은 이름+’.stories.tsx’로 파일을 생성해주면 됩니다.
테스트를 위해 StoryButton을 추가해줍니다!
components ㄴ atoms ㄴ button ㄴ index.tsx ㄴ StoryButton.tsx ㄴ StoryButton.stories.tsx
이제 StoryButton.tsx에 컴포넌트를 정의해주고 StoryButton.stories.tsx에서 해당 컴포넌트의 스토리를 작성합니다.
// StoryButton.tsx import React, { useState } from "react"; import styled from "styled-components"; interface Prop { isSelected: boolean; devideNumber: string; content: string; } const StoryButton: React.FC<Prop> = ({ isSelected, devideNumber, content }) => { const [selected, setSelected] = useState<boolean>(isSelected); const isTablet = window.innerWidth < 768; return ( <ItemBody selected={selected} onClick={() => setSelected(!selected)}> <Inner flex="3">{devideNumber}번</Inner> <Inner flex="7">{truncateString(content, isTablet ? 16 : 24)}</Inner> </ItemBody> ); }; export default StoryButton; const Inner = styled.div<{ flex: "3" | "7" }>` flex: ${({ flex }) => flex}; border-right: ${({ flex }) => (flex === "3" ? "1px solid" : "none")}; justify-content: center; align-items: center; height: 24px; display: flex; padding: 14px; line-height: 1.25; `; const ItemBody = styled.div<{ selected: boolean }>` cursor: pointer; flex: 10; width: 100%; height: 54px; display: flex; border: 1px solid var(--main-color); border-radius: 10px; align-items: center; justify-content: center; color: ${({ selected }) => (selected ? "#fff" : "#6b6d78")}; background-color: ${({ selected }) => (selected ? "var(--main-color)" : "#fff")}; `;
// StoryButton.stories.tsx import React from "react"; import { Story } from "@storybook/react"; import StoryButton, { SelectUnitProps } from "./MainSelectUnit"; export default { title: "StoryButton", component: StoryButton, }; const Template: Story<SelectUnitProps> = (args) => <MainSelectUnit {...args} />; // 들어갈 props를 이렇게 정해줄 수 있습니다. export const Selected = Template.bind({}); Selected.args = { isSelected: true, devideNumber: "01", content: "1번 버튼입니다", }; // Selected라는 이름의 story입니다. 테스트해보고싶은 props를 여기서 줄 수 있습니다. export const NotSelectedLongContent = Template.bind({}); NotSelectedLongContent.args = { isSelected: false, devideNumber: "02", content: "2번 버튼입니다. 내용이 아주길어용아주아주아주아주", }; // NotSelectedLongContent 이름의 story입니다.
export const Default = Template.bind({}); 는 그냥 정해진 문법이라 이대로 쓰면 됩니다.
.args = {
… }
내에 스토리북에서 어떻게 이 컴포넌트가 보일지 argument를 넣어 테스트해볼 수 있습니다.
그럼 이제 $ yarn storybook 명령어를 통해 방금 작성한 story를 볼 수 있습니다.
아까 StoryButton으로 지어둔 제목을 왼쪽 탭에서 확인할 수 있습니다.
그리고 작성해둔 Selected와 NotSelectedLongContent 두가지의 테스트UI를 화면에서 볼 수 있어요.
그 아래 controler를 통해 props를 storybook 내에서 조작할 수도 있습니다!
현재는 세가지의 prop뿐이지만 아주 많은 props를 가진 복잡한 컴포넌트일 경우 유용하게 쓰이겠죠?
참고한 사이트
https://deku.posstree.com/ko/react/nextjs/storybook/start/
[Next.js] Storybook
TypeScript를 기반으로 한 Next.js 프로젝트에 Storybook를 사용하여 컴포넌트 주도 개발을 해 봅시다.
deku.posstree.com
https://www.js2uix.com/frontend/storybook-study-step1/
Storybook - 소개 및 설치 (1)
이번 포스트부터는 Storybook이란 툴에 대해서 알아볼까 합니다.
www.js2uix.com
728x90'Java Script & Type Script > Favorites' 카테고리의 다른 글
[TS] 엔터쳐서 실행하기 유틸함수 만들기 (0) 2023.07.04 [REACT] 데시벨측정 자동녹음종료기능 custom hook (0) 2023.06.25 [React] 네이버 자동로그인 따라하기 (0) 2023.06.19 [Library] React-slick, Apex-charts 라이브러리 이용법 -리액트로 캐러셀 구현, 도넛그래프, 반원그래프, 오각형그래프, 막대그래프 그리기 (0) 2023.06.15 [React] 리팩토링 - 컴포넌트 역할 분리 (0) 2023.04.20