하루루카
루카의 개발 일지
하루루카
전체 방문자
오늘
어제
  • 분류 전체보기 (62)
    • React (10)
    • vue.js (5)
    • javascript (6)
    • 자격증 (5)
    • 기타 (8)
    • 코딩테스트 (11)
    • 프론트 CS (15)
    • NodeJs (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • react
  • vuetify
  • 코딩테스트
  • 자바스크립트
  • 기술면접
  • AWS
  • node
  • codedeploy
  • CI/CD
  • 쿠버네티스
  • nodejs
  • nextjs
  • 프론트엔드
  • socket
  • 11655
  • VUE
  • 백준
  • GithubActions
  • vuex
  • jest

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
하루루카

루카의 개발 일지

React

React Story Book 알아보기

2022. 12. 20. 16:18

갑자기.. React 관련한 글이네요..ㅎㅎ

개인 노션에 정리해둔 게 계속 쌓여서 차근차근 블로그에 작성하고 있는 단계이고

오늘은 React Story Book에 대해 정리해보도록하겠습니다

 

소스 코드는 아래 GIT에서 확인 가능하십니다

https://github.com/jungHyeonS/React-stroybook

 

GitHub - jungHyeonS/React-stroybook: react-stroybook-study

react-stroybook-study. Contribute to jungHyeonS/React-stroybook development by creating an account on GitHub.

github.com

 

StoryBook 이 뭘까?

스토리북은 다양한 방식으로 사용되고 있는 UI 컴포넌트 개발 도구입니다. 단순히 회사 UI라이브러리를 내부 개발자들을 위해 문서화할 수도 있고, 외부 공개용 디자인 시스템을 개발하기 위한 기본 플랫폼으로도 사용할 수 있습니다

 

즉 컴포넌트들을 문서화할 수 있도록 도와주는 오픈소스 도구입니다

 

스토리북의 기본 구성단위는 스토리(Story)이며, 하나의 UI 컴포넌트는 보통 하나 이상의 Story를 가지게 됩니다

각 Story는 해당 UI 컴포넌트가 어떻게 사용될수 있는지 보여주는 하나의 예시입니다

 

스토리북을 사용하면 UI컴포넌트가 각각 독립적으로 어떻게 실제로 렌더링 되는지 직접 시각적으로 테스트하면서 개발을 진행할 수 있습니다

해당 UI라이브러리를 사용하는 개발자 입장에서도 코드를 보지 않고 미리 각 UI 컴포넌트를 체험해보고 사용할 수 있습니다

 

 

스토리북을 쓰는 이유

1. 개별 정돈의 편리합니다

2. 재사용성을 고려한 디자인과 개발이 가능합니다

3. 컴포넌트 테스트에 용이합니다

 

재사용성의 필요성

1. 불필요한 작업을 줄여줍니다

2. 안정적으로 검증된 코드를 사용할 수 있습니다

3. 캡슐화를 통해 테스트가 쉬워집니다

 

그러면 스토리북 예제 프로젝트를 개발해보도록 하겠습니다

해당 프로젝트는 CRA 기반으로 개발하였습니다

 

StoryBook 설치 및 세팅

npx -p @storybook/cli sb init

해당 명령어를 실행하게 되면 . storybook, src/stories 폴더가 생성되게 됩니다

.storybook : Storybook 설정 파일들이 포함된 폴더입니다

src/stories : Storybook 예제 컴포넌트 폴더 입니다

 

StoryBook 실행

package.json 파일을 열어보게 되면 storybook이라는 빌드 스크립트가 추가되어있습니다

npm run storybook

이 명령어를 입력하게 되면 아래와 같이 스토리북 로컬 화면이 실행되게 됩니다

 

 

이 포스팅 예제에서는 버튼 컴포넌트와 여러 개의 div로 구성되어있는 stack 컴포넌트를 만들어 보도록 하겠습니다

 

우선 src/stories 폴더를 보게 되면 많은 파일들이 있는데 전부다 삭제해주도록 하겠습니다

 

 

Button 컴포넌트 생성

src/components 폴더에 button 컴포넌트를 생성해보도록 하겠습니다

* prop-types 모듈은 npm install prop-types 해주시면 됩니다

 

Button 컴포넌트는 props로 label, backgroundColor, size, handleClick(클릭이벤트)를 받게 되며

이 props들은 이후 스토리를 만들 때 사용하게 됩니다

import PropTypes from "prop-types"

function Button({label,backgroundColor="red",size="md",handleClick}){
    let scale = 1
    if(size === "sm") scale = 0.75
    if(size === "lg") scale = 1.5;
    const style = {
        backgroundColor,
        padding : `${scale * 0.5}rem ${scale * 1}rem`,
        border : "none"
    }
    return(
        <button onClick={handleClick} style={style}>
            {label}
        </button>
    )
}

Button.prototype = {
    label : PropTypes.string,
    backgroundColor : PropTypes.string,
    size : PropTypes.oneOf(["sm","md","lg"]),
    handleClick: PropTypes.func
}
export default Button

 

예제용 버튼 컴포넌트를 생성하였으니 이 버튼에 대한 스토리를 만들어보도록 하겠습니다

 

Button.stories 생성

우선 src/stories/Button.stories.js 파일을 생성을 하고 우선 아래 코드를 추가해줍니다

import Button from "../components/Button";

//실제 스토리 객체
export default {
    title : "Components/Button",
    component : Button,
    argTypes : {handleClick : {action : "handleClick"}}
}

위에서 만든 Button 컴포넌트를 불러오고 실제 스토리에 해당하는 객체를 만들어줍니다

해당 객체에서 내가 만들 스토리에 제목(타이틀)과 어떤 컴포넌트를 지정할지에 대해 명시를 해주고

만약 클릭이벤트가 있다면 argTypes에 이벤트를 지정해주면 됩니다

title : 스토리의 제목

component : 스토리에 적용할 컴포넌트

argTypes : 컴포넌트에 이벤트

 

자 그러면 이상태 면 스토리가 만들어질까요?

 

아닙니다 위에서 작성한 Button 컴포넌트는 props들을 가지고 있기 때문에 해당 props들을 지정해줘야 합니다

자바스크립트에 bind를 이용을 해야 되기에 다음과 같은 코드를 작성합니다

const Template = args => <Button {...args}/>

export const Red = Template.bind({});
Red.args = {
    backgroundColor : 'red',
    label : 'Press me',
    size : "md",
}

Button 컴포넌트를 리턴하는 Template 객체를 만들고

해당 객체에 args로 Button 컴포넌트에 Props들을 지정한 후에 전달합니다

그러면 backgroundColor, label, size Prop들이 Button 컴포넌트에 전달하게 됩니다

 

이후 저장한 후 스토리북 페이지를 한번 보도록 하겠습니다

 

 

아까 저희가 만든 Button 이 스토리북에 나오게 되었습니다, args로 지정한 backgroundColor, label, size도 정확하게 표시가 되었습니다

 

그리고 여기서 스토리북의 강점이 나옵니다, 우리가 만든 스토리에 Controls 부분을 조작해보면 저희가 입력한 대로 컴포넌트가 실행되는 것을 볼 수 있습니다

 

그리고 Red 컴포넌트 말고도 Green, small과 같은 이름의 컴포넌트를 추가적으로 만들고 싶다면

bind 객체를 아래와 같이 여러 개 만들면 됩니다

export const Green = Template.bind({});
Green.args = {
    backgroundColor : 'green',
    label : 'Press me',
    size : "lg",
}

export const Small = Template.bind({});
Small.args = {
    backgroundColor : 'red',
    label : 'Press me',
    size : "sm",
}

export const Large = Template.bind({});
Large.args = {
    backgroundColor : 'red',
    label : 'Press me',
    size : "lg",
}

export const LongLabel = Template.bind({});
LongLabel.args = {
    backgroundColor : 'red',
    label : 'Press me assasdasdas dasdasdas dasdasdasdasdasd',
    size : "md",
}

 

 

다음은 입력한 숫자만큼 div가 생성되는 stack 컴포넌트를 만들어보도록 하겠습니다

Stack 컴포넌트 생성

src/components/Stack.js 파일에 아래와 같이 생성하였습니다

 

여기서 중요한 점은 children props입니다

chidren은 stack 컴포넌트를 사용할 때 <stack></stack>과 같이 사용하게 되는데

이때 태그와 태그 사이에 모든 내용일 넘겨지게 됩니다

 

그 외는 Button 컴포넌트와 같이 props를 받고 컴포넌트를 그리게 됩니다

import PropTypes from "prop-types"

function Stack({children,spacing=2,direction="row",wrap=false}){
    const style = {
        display : "flex",
        gap : `${spacing * 0.25}rem`,
        flexWrap : wrap ? "wrap" : "nowrap",
        flexDirection : direction
    }
    return <div style={style}>{children}</div>
}

Stack.prototype = {
    spacing : PropTypes.number,
    wrap : PropTypes.bool,
    directio : PropTypes.oneOf(["row","column"])
}

export default Stack;

 

Stack.stories 생성

우선 아래와 같이 코드를 작성했습니다

import Stack from "../components/Stack";

//실제 스토리 객체
export default {
    title : "Components/Stack",
    component : Stack,
    argTypes:{
        numberOfChildren : {type : "number",defaultValue : 4}
    }
}

Button stories를 만들 때와 동일합니다

스토리에 객체에 제목과, 적용할 컴포넌트를 명시를 합니다

이때 이번에는 argTypes에 액션이 아니라 numberOfChildren이라는 변수를 지정했습니다

이 numberOfChidren은 스토리북에서 입력할 div의 개수를 명시하였습니다

 

이후 템플릿을 생성을 하는데 이 템플릿 같은 경우는 위에서 지정한 numberOfChidren 만큼 map을 돌려서

<stack></stack> 태그 안에 div를 생성하는 템플릿입니다

const Template = ({numberOfChildren,...args}) => (
    <Stack {...args}>
        {[...Array(numberOfChildren).keys()].map(n => (
            <div style={{width : "50px", height : "50px",backgroundColor:"red",display:"flex",justifyContent:"center",alignItems:"center"}}>
                {n + 1}
            </div>
        ))}
    </Stack>
)

이렇게 된다면 numberOfChidren 만큼 div가 생성이 되고

stack 컴포넌트에 chidren props 를통하여 <stack></stack> 태그 안에 있는 모든 내용이 전달됩니다

 

이 이후에는 비슷합니다 bind객체를 생성하고 해당 객체에 원하는 args를 전달해주면 됩니다

export const Horizontal = Template.bind({})
Horizontal.args = {
    direction : "row",
    spacing : 2,
    wrap : false
}

export const Vertical = Template.bind({})
Vertical.args = {
    direction : "column",
    spacing : 2,
    wrap : false
}

export const NoSpacing = Template.bind({})
NoSpacing.args = {
    direction : "row",
    spacing : 0,
    wrap : false
}


export const WrapOverflow = Template.bind({})
WrapOverflow.args = {
    numberOfChildren:40,
    direction : "row",
    spacing : 2,
    wrap : true
}

export const Empty = Template.bind({})
Empty.args = {
    numberOfChildren:0,
    direction : "row",
    spacing : 0,
    wrap : false
}

 

여기까지 작성한 후에 스토리북 화면을 보게 되면 stack이라는 폴더가 하나 생성이 되어있으며

numberOfChidren의 값을 변경하면 div의 개수가 달라지는 것을 확인할 수 있습니다

 

 

 

여기까지 해서 스토리북에 대해 알아보았습니다

이 프로젝트는 간단한 예제들로 구성이 되어있는 프로젝트이지만

스토리북 홈페이지에 들어가 보시면 다양한 기업의 스토리북을 확인하실수 있습니다

'React' 카테고리의 다른 글

React CI/CD 구축 해보기 2(EC2 + Github Actions + CodeDeploy)  (0) 2023.03.22
React CI/CD 구축 해보기 1(EC2+Github Actions + CodeDeploy)  (0) 2023.03.19
리액트 디자인 패턴 알아보기  (0) 2023.01.16
React StoryBook 배포 해보기  (0) 2023.01.09
React Recoil 알아보기  (0) 2023.01.01
    'React' 카테고리의 다른 글
    • React CI/CD 구축 해보기 1(EC2+Github Actions + CodeDeploy)
    • 리액트 디자인 패턴 알아보기
    • React StoryBook 배포 해보기
    • React Recoil 알아보기
    하루루카
    하루루카

    티스토리툴바