CDD ๊ฐ๋ฐ ๋๊ตฌ ์ค ํ๋๋ก, ๊ฐ ์ปดํฌ๋ํธ๋ค์ ๋ฐ๋ก ๋ณผ ์ ์๊ฒ ๊ตฌ์ฑํ๊ธฐ ๋๋ฌธ์ ํ ๋ฒ์ ํ๋์ ์ปดํฌ๋ํธ์์ ์์ ํ ์ ์์ผ๋ฉฐ ๋ ๋ฆฝ์ ์ธ ๊ฐ๋ฐ ํ๊ฒฝ์์ ์คํ๋๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ค์ํ ์ํฉ์ ๊ตฌ์ ๋ฐ์ง ์๊ณ UI ์ปดํฌ๋ํธ๋ฅผ ์ง์ค์ ์ผ๋ก ๊ฐ๋ฐํ ์ ์๋ค.
๋ํ, ์ฌ์ฌ์ฉ์ฑ์ ๋์ด๊ธฐ ์ํด ์ปดํฌ๋ํธ๋ฅผ ๋ฌธ์ํํ๊ณ , ๋ค์ํ ํ ์คํธ๊ฐ ๊ฐ๋ฅํ๋๋ก ์ปดํฌ๋ํธ๋ฅผ ์๊ฐํํ์ฌ ์ฌ์ ์ ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํ ์ ์๋๋ก ํ๋ค.
npx create-react-app <ํ๋ก์ ํธ ๋ช
>
๋ช
๋ น์ด๋ฅผ ์
๋ ฅํด ์ค์นํ ํ, ์๋ก์ด react ํ๋ก์ ํธ๋ฅผ ์์ฑํ๋ค.npx storybook init
๋ช
๋ น์ด๋ฅผ ์
๋ ฅํด storybook์ ์ค์นํ๋ค../storybook = storybook ๊ด๋ จ ์ค์ ํ์ผ
/src/stories = storybook ์์ ํ์ผ๋ค
npm run storybook
๋ช
๋ น์ด๋ฅผ ์
๋ ฅํด storybook์ ์คํํ๋ค.import React from "react";
// title์ h1 ์์์ textContent, textColor์ ๊ธ์์์ด ๋๋ props ์ด๋ค.
const Title = ({title, textColor}) => (
<h1 style={{color: textColor}}>{title}</h1>
);
export default Title;
// ์์์ ์์ฑํ ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์จ๋ค.
import Title from "./Title";
// title : ์ปดํฌ๋ํธ ์ด๋ฆ, '/'๋ฅผ ๋ฃ์ด ์นดํ
๊ณ ๋ฆฌํ ๊ฐ๋ฅ.
// component : ์ด๋ค ์ปดํฌ๋ํธ๋ฅผ ๊ฐ์ ธ์์ ์คํ ๋ฆฌ๋ก ๋ง๋ค ๊ฒ์ธ์ง ๋ช
์ํ๋ค.
// argTypes : ์ปดํฌ๋ํธ์ ํ์ํ ์ ๋ฌ์ธ์์ ์ข
๋ฅ์ ํ์
์ ์ ํ๋ค.
// title, textColor์ด๋ผ๋ ์ ๋ฌ์ธ์์ text ํ์
์ด ํ์ํจ์ ์๋ฏธํจ.
export default {
title: "Practice/Title",
component: Title,
argTypes: {
title: { control: "text" },
textColor: {control: "text"}
}
}
// Title ์ปดํฌ๋ํธ๊ฐ args๋ฅผ ์ ๋ฌ๋ฐ์ props๋ก ๋ด๋ ค์ฃผ๋ ํ
ํ๋ฆฟ์ ์์ฑํ๋ค.
const Template = (args) => <Title {...args} />
// Storybook์์ ํ์ธํ๊ณ ์ถ์ ์ปดํฌ๋ํธ๋ export const๋ก ์์ฑํ๋ค.
// Template.bins({}); ๋ ์ ํด์ง ๋ฌธ๋ฒ
// ํ
ํ๋ฆฟ์ ์ฌ์ฉํ์ฌ Storybook์ ๋ฃ์ ์คํ ๋ฆฌ ์์ฑ
export const RedTitle = Template.bind({});
// ๋ง๋ค์ด์ค ์คํ ๋ฆฌ์ ์ ๋ฌ์ธ์๋ฅผ ์์ฑ
// 1. RedTitle
RedTitle.args= {
title: "Red Title",
textColor: "red"
}
// ํ
ํ๋ฆฟ์ ์ฌ์ฉํ์ฌ Storybook์ ๋ฃ์ ์คํ ๋ฆฌ ์์ฑ 2.
// 2. BlueTitle
export const BlueTitle = Template.bind({});
// ๋ง๋ค์ด์ค ์คํ ๋ฆฌ์ ์ ๋ฌ์ธ์๋ฅผ ์์ฑ2
BlueTitle.args= {
title: "Blue Title",
textColor: "blue"
}
// ์ ๋ฌ์ธ์๋ฅผ ์ง์ ๋ฐ๋ ์คํ ๋ฆฌ ์์ฑ
// 3. UserTitle
export const StorybookTitle = (args) =>{
return <Title {...args} />
}
import React from "react";
import styled from "styled-components"
const StyledButton = styled.button`
// props.color๊ฐ ์์ผ๋ฉด props.color, ์๋๋ฉด ํฐ์์ ๋ฐฐ๊ฒฝ์์ผ๋ก
background: ${(props) => props.color || "white" };
// props.size๊ฐ bug์ด๋ฉด 200px, ์๋๋ฉด 100px๋ฅผ ๋๋น๋ก
width: ${(props) => (props.size === "big" ? "200px" : "100px") };
// props.size๊ฐ "big"์ด๋ฉด 80px, ์๋๋ฉด 40px๋ฅผ ๋์ด๋ก
height: ${(props) => (props.size === "big" ? "80px" : "40px") };
`
const Button = ({color, size, text}) => (
// ์์์ ์์ฑํ props + text๋ฅผ ๋ฐ์ textContent๋ก ์ฌ์ฉ
<StyledButton color={color} size={size}>{text}</StyledButton>
);
export default Button;
// ์ปดํฌ๋ํธ๋ฅผ ๋ถ๋ฌ์จ๋ค.
import Button from "./Button";
export default {
title: "Practice/Button",
component: Button,
argTypes: {
color: { control: 'color'},
size: { control: { type:'radio', options : ['big', 'small'] }},
text: { control: 'text'}
}
};
export const StorybookButton = (args) => (
<Button {...args}></Button>
)
Reference: ์ฝ๋์คํ ์ด์ธ