Component Driven Development가 트렌드로 자리 잡게 되면서- 이를 지원하는 도구 중 하나인 Component Explorer (컴포넌트 탐색기) 가 등장했다.
- Component Explorer에는 많은 UI 개발 도구가 다양하게 있는데 그중 하나가
Storybook이다.
Storybook이란?
Storybook은 UI 개발 즉, Component Driven Development를 하기 위한 도구이다.
- 각각의 컴포넌트들을 따로 볼 수 있게 구성해 주어 한 번에 하나의 컴포넌트에서 작업할 수 있다.
- 복잡한 개발 스택을 시작하거나, 특정 데이터를 데이터베이스로 강제 이동하거나, 애플리케이션을 탐색할 필요 없이 전체 UI를 한눈에 보고 개발할 수 있다.
- Storybook은 재사용성을 확대하기 위해 컴포넌트를 문서화하고, 자동으로 컴포넌트를 시각화하여 시뮬레이션할 수 있는 다양한 테스트 상태를 확인할 수 있다. 이를 통해 버그를 사전에 방지할 수 있도록 도와준다.
- 또한 테스트 및 개발 속도를 향상시키는 장점이 있으며, 애플리케이션 또한 의존성을 걱정하지 않고 빌드할 수 있다.
Storybook 사용 이유
- Storybook은 기본적으로 독립적인 개발 환경에서 실행된다.
- 개발자는 애플리케이션의 다양한 상황에 구애받지 않고 UI 컴포넌트를 집중적으로 개발할 수 있다.
아래 예시처럼 회사의 내부 개발자들을 위해 문서화(documentation)를 하여 회사의 UI 라이브러리로써 사용하거나,
외부 공개용 디자인 시스템(Design System)을 개발하기 위한 기본 플랫폼으로 사용할 수 있다.
Storybook에서 지원하는 주요 기능
- UI 컴포넌트들을 카탈로그화하기
- 컴포넌트 변화를 Stories로 저장하기
- 핫 모듈 재 로딩과 같은 개발 툴 경험을 제공하기
- 리액트를 포함한 다양한 뷰 레이어 지원하기
컴포넌트를 시뮬레이션, 문서화하는 방법
우선 Create React App을 활용해서 리액트 프로젝트를 만들어준다.
npx create-react-app storybook-practice
폴더가 생성되면, 폴더 안에서 다음 명령어를 입력하여 Storybook을 설치한다.
- 이 명령어는 package.json 을 보고 사용 중인 프론트엔드 라이브러리에 맞는 Storybook 사용 환경을 알아서 만들어주기 때문에, 꼭 React가 아니더라도 다양한 프론트엔드 라이브러리에서 사용할 수 있다.
npx storybook init
Storybook 설치가 완료되면, /.storybook 폴더와 /src/stories 폴더가 생성된 것을 확인할 수 있다.
- /.storybook 폴더에는 Storybook 관련 설정 파일이,
- /src/stories 폴더에는 Storybook 예시 파일들이 들어있다.
이제 터미널 창에 다음 명령어를 입력하여 Storybook을 실행한다.
npm run storybook
명령어를 입력하면 React가 localhost:3000으로 접근하듯이, localhost:6006으로 접근하여 Storybook을 실행시킨다.
- Storybook을 실행하면 /src/stories 폴더 안에 있던, Storybook에서 만들어놓은 예시 스토리를 확인할 수 있다.
- 이렇게 Storybook을 사용하면 애플리케이션을 실행하고 이벤트를 통해 상태를 변경하는 과정을 거치지 않아도 상태 변화에 따른 컴포넌트의 변화를 확인할 수 있다.
Storybook 코드를 작성하기
그 전에, 튜토리얼을 진행하면서 사용할 Styled-Components를 먼저 설치한다.
npm install styled-components
간단한 스토리 작성하기
설치를 완료했다면, 간단한 스토리를 직접 작성해 본다.
src 폴더 안에 Title.js 파일을 하나 만들고, 다음과 같은 간단한 React 컴포넌트를 하나 만들어 export 해준다.
import React from "react";
// title은 h1 요소의 textContent, textColor은 글자색이 되는 props이다.
const Title = ({title, textColor}) => (
<h1 style={{color: textColor}}>{title}</h1>
);
export default Title;
그리고 같은 위치인 src 폴더 안에 Title.stories.js 파일을 하나 만든다.
- /.storybook 안에 있는 Storybook 설정 파일에 의해서 컴포넌트 파일과 똑같은 파일 이름에 .stories를 붙여 파일을 만들면 알아서 스토리로 인식한다.
- Title.stories.js 는 다음과 같이 작성한다.
// 앞에서 작성한 컴포넌트를 불러온다.
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로 작성한다.
// 템플릿을 사용하여 Storybook에 넣어줄 스토리를 하나 만들어주었다.
// Template.bind({}); 는 정해진 문법이라고 생각하고 사용하면 된다.
// ** 함수의 복사본을 만드는 표준 JavaScript의 한 기법
export const RedTitle = Template.bind({});
// 만들어준 스토리의 전달인자를 작성해준다.
RedTitle.args= {
title: "Red Title",
textColor: "red"
}
// 스토리를 하나 더 만든다.
export const BlueTitle = Template.bind({});
// 스토리의 전달인자를 작성한다.
BlueTitle.args= {
title: "Blue Title",
textColor: "blue"
}
Title.stories.js 파일을 저장하고 Storybook을 확인해 보면,
Storybook은 핫 모듈 리로딩을 지원하기 때문에 따로 새로고침을 하지 않아도 변경 사항을 바로 확인할 수 있다.
- title: “Practice/Title” 로 작성해 준 코드가 좌측 메뉴에서 카테고리로 적용된 것을 확인할 수 있습니다. 이렇게 Practice라는 카테고리에 Title 외의 스토리도 담아줄 수 있다.
- title.stories.js 안에서 템플릿을 사용해 만든 두 개의 스토리가 Title 안에 들어있는 것을 볼 수 있다.
- 각 스토리에서는 작성해 준 전달인자도 확인할 수 있고,
- 전달인자에 따라 결과물이 달라진 것도 볼 수 있다.
전달인자를 직접 받는 스토리 작성하기
이번에는 전달인자를 직접 받는 스토리를 만들어본다. 앞서 만들었던 두 스토리 바로 밑에 다음과 같은 스토리를 하나 더 작성해 준다.
...
export const StorybookTitle = (args) =>{
return <Title {...args} />
}
이 스토리는 템플릿을 활용하지 않고 바로 전달인자를 받고있다. 저장 후 다시 Storybook을 확인해보면,
이번에 만든 스토리는 전달 인자를 직접 작성해 주면 거기에 맞춰 모습이 변하는 것을 볼 수 있다.
전달 인자를 직접 받으면서 Styled Components를 사용해서 만든 컴포넌트를 스토리로 작성하기
이번에는 전달 인자를 직접 받으면서, Styled Components를 사용해서 만든 컴포넌트를 스토리로 만들어보겠다.
우선, Button.js라는 파일을 하나 만들고 다음과 같은 컴포넌트를 작성한다.
import React from "react";
import styled from "styled-components";
const StyledButton = styled.button`
//props.color가 있으면 props.color를, 그렇지 않으면 흰색을 배경색으로 사용한다.
background: ${(props) => props.color || "white"};
//props.size가 'big'이면 200px를, 그렇지 않으면 100px을 너비로 사용한다.
width: ${(props) => (props.size === "big" ? "200px" : "100px")};
//props.size가 'big'이면 80px를, 그렇지 않으면 4px를 높이로 사용한다.
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,
// 이번에 작성한 전달인자의 타입은 Storybook을 보고 직접 확인해보세요.
argTypes: {
color: { control: 'color'},
size: { control: 'radio', options : ['big', 'small'] },
// 또는 size: { control: { type: 'radio' }, options: ['big', 'small'] }
text: { control: 'text'}
}
};
export const StorybookButton = (args) => (
<Button {...args}></Button>
)
코드를 저장하고 Storybook을 확인해 보면 이번에 만든 스토리에서는
- control: ‘color’ 는 색상을 직접 골라 인자를 전달해줄 수 있고,
- control: { ‘radio’, options: [] } 는 radio 버튼을 통해 바로 전달인자를 받는 모습을 볼 수 있다.
다른 예
// WithAnImage.js
export function WithAnImage(props) {
return <img style={{ width: props.width }} src={props.src} alt={props.alt} />;
}
// WithAnImage.stories.js
import { WithAnImage } from "./WithAnImage";
import Logo from "../Image/Codestates_Fulllogo_Color.png";
import SmallLogo from "../Image/smallLogo.jpeg";
export default {
title: "Example/Logo",
component: WithAnImage,
};
const Template = (args) => <WithAnImage {...args} />;
export const TypeOne = Template.bind({});
TypeOne.args = {
src: Logo,
alt: "Logo",
width: "300px",
};
export const TypeTwo = (2)____________;
TypeTwo.args = {
src: SmallLogo,
alt: "SmallLogo",
width: "250px",
};
이 외에도 다양한 타입과 작성 가능한 속성들이 참고하려면 : Storybook 공식 문서
'FE > UI & UX' 카테고리의 다른 글
SEO (0) | 2023.04.26 |
---|---|
웹표준 (0) | 2023.04.26 |
[UI/UX] 와이어프레임 & 프로토타입 (0) | 2023.04.13 |
[UI] UI 디자인 패턴 / UI 레이아웃 구성법 (컬럼 그리드 시스템) (1) | 2023.04.13 |
[UX] 피터 모빌(Peter Morville)의 UX 7요소 / User Flow (1) | 2023.04.13 |