[ ๐Ÿ“– storybook] ์‚ฌ์šฉ๋ฒ•

dsfasdยท2022๋…„ 10์›” 27์ผ
0

storybook์€ UI ์ปดํฌ๋„ŒํŠธ ๊ฐœ๋ฐœ ๋„๊ตฌ์ด๋‹ค.

์‹ค์ œ ์ปดํฌ๋„ŒํŠธ์— ์ผ์ผํžˆ ์Šคํƒ€์ผ์„ ์ž…ํž ํ•„์š” ์—†์ด,
๋‹ค์–‘ํ•œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ ์ ์šฉ์‹œ์ผœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


storybook ์„ค์น˜ ๋ฐ ์‹คํ–‰

์„ค์น˜

npx storybook init

์‹คํ–‰

npx storybook init

torybook ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด, /.storybook ํด๋”์™€ /src/stories ํด๋”๊ฐ€ ์ƒ์„ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

/.storybook ํด๋”์—๋Š” Storybook ๊ด€๋ จ ์„ค์ • ํŒŒ์ผ์ด,
/src/stories ํด๋”์—๋Š” Storybook ์˜ˆ์‹œ ํŒŒ์ผ๋“ค์ด ๋“ค์–ด์žˆ์Šต๋‹ˆ๋‹ค.


  1. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์— ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑ ํ›„ export ํ•ด์ค€๋‹ค.
    props๋ฅผ ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น์œผ๋กœ title, textColor ์ธ์ž๋กœ ๋„ฃ์–ด์ค€๋‹ค.

Title.js

import React from "react";

// title์€ h1 ์š”์†Œ์˜ textContent, textColor์€ ๊ธ€์ž์ƒ‰์ด ๋˜๋Š” props์ž…๋‹ˆ๋‹ค.
const Title = ({title, textColor}) => (
<h1 style={{color: textColor}}>{title}</h1>
);

export default Title;

  1. ์ด ๋ถ€๋ถ„์ด ์‹ค์ œ๋กœ ์Šคํ† ๋ฆฌ๋ถ์—์„œ ํŽผ์ณ์ง€๋ฉด ๋‚˜์˜ค๋Š” ๋‚ด์šฉ์ด๋‹ค.

์šฐ์„  Title ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

export default { title: component: argTypes: ... }

title :
์ปดํฌ๋„ŒํŠธ ์ด๋ฆ„์œผ๋กœ, '/'๋ฅผ ๋„ฃ์–ด ์นดํ…Œ๊ณ ๋ฆฌํ™” ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ดํ›„ ์˜ˆ์‹œ์—์„œ ์กฐ๊ธˆ ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

component :
์–ด๋–ค ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ€์ ธ์™€์„œ ์Šคํ† ๋ฆฌ๋กœ ๋งŒ๋“ค ๊ฒƒ์ธ์ง€ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.

argTypes :
์ปดํฌ๋„ŒํŠธ์— ํ•„์š”ํ•œ ์ „๋‹ฌ์ธ์ž์˜ ์ข…๋ฅ˜์™€ ํƒ€์ž…์„ ์ •ํ•ด์ค๋‹ˆ๋‹ค.
์ง€๊ธˆ์€ title, textColor์ด๋ผ๋Š” ์ „๋‹ฌ์ธ์ž์— text ํƒ€์ž…์ด ํ•„์š”ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

Title.stories.js

import Title from "./Title";

//export default์—๋Š” story์— ์ ํž json ํŒŒ์ผ์ฒ˜๋Ÿผ ์–‘์‹์„ ๋ช…์„ธํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ž.  
export default {
    title: "Practice/Title", 
    component: Title,
    argTypes: {
        title: { control: "text" },
        textColor: {control: "text"}
    }
}

// ํ…œํ”Œ๋ฆฟ์œผ๋กœ props๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ ๋‚ด๋ ค์ฃผ์ž. 
// ํ…œํ”Œ๋ฆฟ์„ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ์ด ํ…œํ”Œ๋ฆฟ์—์„œ๋Š”
// Title ์ปดํฌ๋„ŒํŠธ๊ฐ€ args๋ฅผ ์ „๋‹ฌ๋ฐ›์•„ props๋กœ ๋‚ด๋ ค์ค๋‹ˆ๋‹ค.
const Template = (args) => <Title {...args} />

// Storybook์—์„œ ํ™•์ธํ•˜๊ณ  ์‹ถ์€ ์ปดํฌ๋„ŒํŠธ๋Š” export const๋กœ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
// ํ…œํ”Œ๋ฆฟ์„ ์‚ฌ์šฉํ•˜์—ฌ Storybook์— ๋„ฃ์–ด์ค„ ์Šคํ† ๋ฆฌ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
// Template.bins({}); ๋Š” ์ •ํ•ด์ง„ ๋ฌธ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์‚ฌ์šฉํ•˜์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.
export const RedTitle = Template.bind({});
// ๋งŒ๋“ค์–ด์ค€ ์Šคํ† ๋ฆฌ์˜ ์ „๋‹ฌ์ธ์ž๋ฅผ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.
RedTitle.args= {
    title: "Red Title",
    textColor: "red"
}

// ์Šคํ† ๋ฆฌ๋ฅผ ํ•˜๋‚˜ ๋” ๋งŒ๋“ญ๋‹ˆ๋‹ค.
export const BlueTitle = Template.bind({});
// ์Šคํ† ๋ฆฌ์˜ ์ „๋‹ฌ์ธ์ž๋ฅผ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.
BlueTitle.args= {
    title: "Blue Title",
    textColor: "blue"
} 

export const PinkTitle = Template.bind({});
PinkTitle.args = {
  title: "Pink Title",
  textColor: 'pink'
}


export const StorybookTitle = (args) =>{
  return <Title {...args} />
}

storybook ์‘์šฉํ•˜๊ธฐ

props๋กœ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •ํ•˜๊ธฐ.

์•ž ์˜ˆ์ œ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ, ์ด๋ฒˆ์—๋Š” ๊ธฐ๋ณธ๊ฐ’ ์ธ์ž๋ฅผ ์„ค์ •ํ•ด๋‘์—ˆ๋‹ค.

Button.js

import React from "react";
import styled from 'styled-components';


// ์—ฌ๊ธฐ์„œ๋Š” ์ปดํฌ๋„ŒํŠธ์— ๊ธฐ๋ณธ์œผ๋กœ ์ „๋‹ฌํ•  ์ธ์ž๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค. 
const StyledButton = styled.button`
  background: ${(props) => props.color || "pink"}; 
  width : ${(props)=> (props.size === 'big'? '200px':'100px')};
  height: ${(props)=> (props.size === 'big'?'80px':'40px')}
`


// ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—, ๊ธฐ๋ณธ๊ฐ’๋“ค์„ ์ ์šฉ์‹œํ‚จ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋„ฃ์–ด์„œ export ํ•ด์ฃผ์—ˆ๋‹ค. 
const Button = ({color,size,text}) => (
  <StyledButton color={color} size={size} >{text}</StyledButton>
);

export default Button

Button.stories.js

// ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.
import Button from "./Button";


// ์–‘์‹์„ ๋ช…์„ธํ•˜๊ธฐ. title, component, argTypes 
export default {
    title: "Practice/Button",
    component: Button,
    argTypes: {
        color: { control: 'color'},
        size: { control: { type:'radio', options : ['big', 'small'] }},
        text: { control: 'text'}
    }
};

// ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ธ์ž ์ „๋‹ฌ 
const Template = (args) => <Button {...args}></Button>

export const StorybookButton = (args) => (
  <Button {...args}></Button>
)

export const defaultButton = Template.bind({});
defaultButton.args = {
  // ์•„๋ฌด ์ธ์ž๋ฅผ ์ฃผ์ง€ ์•Š์•˜๋”๋‹ˆ, js ํŒŒ์ผ์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •ํ•œ pink ๋ฐฐ๊ฒฝ์ด ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 
  // ์œ„์— ์ž‘์„ฑํ•œ StorybookButton๊ณผ ์œ ์‚ฌํ•œ ๋“ฏ ํ•˜๋‹ค. 
}


export const RedButton = Template.bind({});
RedButton.args = {
  title: "RedButton",
  size:'2em',
  color:'red' //์—ฌ๊ธฐ์„œ๋Š” ์ƒ‰์ƒ์„ ์ง€์ •ํ•ด์ฃผ๋‹ˆ ์ƒ‰์ƒ์ด ๋ฐ˜์˜๋˜์–ด ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
}
profile
๊ธฐ๋ก์„ ์ •๋ฆฌํ•˜๋Š” ๊ณต๊ฐ„!

0๊ฐœ์˜ ๋Œ“๊ธ€