storybook이 무엇인지에 대해 알아보겠습니다!
공식문서에는 뭐라고 나와있을까요?
What is Storybook?
Storybook은 UI 컴포넌트와 페이지를 독립적으로 구축하기 위한 프론트엔드 워크숍입니다. 애플리케이션 전체를 실행하지 않고도 도달하기 어려운 상태와 엣지 케이스를 개발하고 공유하는 데 도움을 줍니다. 수천 개의 팀이 UI 개발, 테스트 및 문서화를 위해 Storybook을 사용하고 있습니다. Storybook은 오픈 소스이며 무료입니다.
한마디로 컴포넌트들이 정리되어있는 문서 라고 할 수 있습니다.
Microsoft Fluent UI React Storybook 예시
Storybook은 다음과 같은 특징을 갖습니다.
Story란?
스토리는 컴포넌트의 다양한 상태와 변형을 시각적으로 보여주기 위해 작성된 예제라고 할 수 있습니다. 각 컴포넌트는 여러개의 스토리를 가질 수 있으며, 각 스토리는 해당 컴포넌트의 특정 상태의 외관과 동작을 검증할 수 있게 해줍니다.
Storybook을 사용하면 개발자가 애플리케이션의 컴포넌트를 직관적으로 이해하고 쉽게 사용할 수 있게 해줍니다. 알다시피 다른 사람의 코드를 직접 살펴보는 것은 꽤나 피곤한 일입니다.
스토리북이 없을 때와 있을 때, 컴포넌트를 가져다 사용하는 방법을 간단히 알아보겠습니다.
Storybook이 없을때
const Button = ({
type = 'button',
label,
variant = 'primary',
size = 'medium',
onClick = () => {}
}: ButtonProps) => {
return (
<ButtonContainer type={type} variant={variant} size={size} onClick={onClick}>
{label}
</ButtonContainer>
);
};
type, label, variant, size를 인자로 받는 간단한 버튼이 있다고 해보겠습니다.
이걸 보고 저희는,'variant, size 에 따라 버튼이 어떻게 변하지?', 'variant, size에는 어떤 속성들이 들어갈 수 있는거지?'라는 생각을 하게됩니다.
그리고 이걸 확인하기 위해 스타일 코드를 보러 가보겠습니다.
export const ButtonVariants: CssType = {
primary: css`
background-color: ${Colors.Primary01};
border: 1px solid ${Colors.Primary01};
color: ${Colors.White};
`,
outline: css`
background-color: ${Colors.White};
border: 1px solid ${Colors.Primary01};
color: ${Colors.Primary01};
`,
disabled: css`
background-color: ${Colors.Primary02};
opacity: 0.5;
border: 1px solid ${Colors.Primary02};
color: ${Colors.White};
`,
};
export const ButtonSizes: CssType = {
small: css`
border-radius: 0.4rem;
font-size: 1rem;
padding: 0.4rem 0.8rem;
`,
medium: css`
border-radius: 0.6rem;
font-size: 1.6rem;
padding: 0.6rem 1.2rem;
`,
large: css`
border-radius: 0.8rem;
font-size: 2rem;
padding: 0.8rem 1.6rem;
`,
};
'아하 이런 속성들이 있구나. 색깔, 테두리, 사이즈 등이 조금씩 바뀌네. 그래서 어떻게 보이는거지? 한번 그려봐야겠다.'
그리고 테스트코드를 작성해서 속성에 따라 여러가지 버튼을 그려봅니다.
<section style={{ width: "20rem" }}>
<Button label={"버튼"} variant={"primary"} />
<Button label={"버튼"} variant={"outline"} />
<Button label={"버튼"} variant={"disabled"} />
<Button label={"버튼"} size={"small"} />
<Button label={"버튼"} size={"medium"} />
<Button label={"버튼"} size={"large"} />
</section>

아 이렇게 사용하고 있구나!
드디어 저희는 버튼이 어떻게 사용되고 있고, 어떻게 가져다 써야할지 알게됐습니다.
그렇다면 Storybook을 사용하면 뭐가 다를까요?
Storybook이 있을 때

딸깍 딸깍 딸깍
Storybook을 이용하여 컴포넌트를 시각적으로 확인하는 것은 훨씬 효율적인 개발을 가능하게 해줍니다!
Storybook은 개발자들 사이에서 뿐만 아니라 디자이너와의 커뮤니케이션도 효율적으로 만들어줍니다.
디자이너와 Storybook을 공유함으로써, 디자이너는 컴포넌트들이 디자인 의도에 맞게 개발되고 있는지 실시간으로 확인할 수 있도록 해주고, 개발자에게 즉각적으로 적절한 피드백을 줄 수 있도록 도와줍니다.
이를 통해, 디자인 시스템이나 스타일 가이드를 공유하며, 디자인-개발 간의 불일치를 줄일 수 있습니다!
이 내용은 Storybook에 대해 제대로 조사하고, 직접 사용해보기 전까지는 예상하지 못했던 부분이었습니다. 저는 Storybook은 그저 컴포넌트를 시각적인 문서로 정리해주는 역할만 한다고 생각했었습니다. 하지만 실제로 사용해보니 Storybook 이 컴포넌트 설계 자체에도 큰 도움을 주는 것을 알 수 있었습니다.
우리는 항상 좋은 컴포넌트를 설계하기 위해 고민하고 노력합니다.
하지만 컴포넌트 설계가 잘못되었다는 것은 언제나 문제가 터지고 나서야 깨닫게 됩니다. 그것도 보통 개발이 이미 한참 진행된 상태에서,,,
‘아, 컴포넌트의 기능이 너무 많다’, ‘아, 이 로직이 컴포넌트 안에 있으면 안됐다’
하지만 Storybook을 사용하게 되면, 컴포넌트를 Storybook에 올리는 순간 에러와 맞닥뜨리며 문제를 깨닫게 됩니다.
Storybook은 독립적인 환경에서 컴포넌트를 그리게 되므로, 컴포넌트의 의존성, 데이터 처리 등에 대해 다시 검토할 수 있게 되고, 이를 통해 더 모듈화되고 재사용 가능한 컴포넌트를 설계할 수 있게 됩니다.
Storybook 의 기능을 확장하고 개발 환경을 더욱 풍부하게 만들어주는 플러그인
Storybook 개발 팀에서 만드는 공식 애드온 뿐 아니라, 사용자들이 만드는 애드온들도 많이 있습니다.
공식문서에 따르면, 문서화, 접근성 테스트, 인터랙티브 컨트롤 등 대부분의 Storybook 기능은 애드온으로 구현된다고 합니다.

몇몇 필수 애드온 들은 스토리북 Init만 해도 자동적으로 설치되는 것을 볼 수 있습니다.
필수 애드온에는 다음과 같은 것들이 있습니다. 자세한 것들은 링크되어있는 공식문서를 참고하시면 좋을 것 같습니다.

Storybook을 설치하면 최상단에 .storybook과 src/stories 가 생성됩니다.
이 아래에서 설명하는 폴더와 파일들은 Storybook을 설치했을 때 초기에 기본적으로 생성되는 파일들입니다.
그러면 하나씩 차근차근 어떤 폴더인지 알아보겠습니다!

.storybook 폴더는 Storybook의 설정 파일들을 모아두는 폴더입니다.
import type { StorybookConfig } from '@storybook/react-vite';
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-onboarding',
'@storybook/addon-links',
'@storybook/addon-essentials',
'@chromatic-com/storybook',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
};
export default config;
main.ts는 storybook의 기본 설정 파일로, 스토리 파일의 위치, 애드온, 웹팩 설정 등을 정의합니다.
아래에서 다시 설명하겠지만, 설정의 경로를 보면
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"]
반드시 스토리 파일이 stories 폴더 안에 있을 필요는 없다는 것을 알 수 있습니다.
import type { Preview } from '@storybook/react';
const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;
preview.tsx는 스토리 렌더링에 영향을 미치는 글로벌 설정과 데코레이터를 정의하는 파일로, 글로벌 스타일이나 컨텍스트 프로바이더 등을 설정 할 수 있습니다.
이외에도 다음과 같은 설정파일들을 추가할 수 있습니다.
manager.ts: Storybook의 UI(스토리 목록, 애드온 패널 등)를 커스터마이징할 수 있는 설정 파일
preview-head.html: 외부 폰트나 스타일시트를 포함할 수 있도록, <head> 태그에 추가할 HTML을 정의하는 파일

컴포넌트의 스토리를 작성하는 파일들을 모아두는 디렉토리입니다.
스토리 파일은 보통 .stories.js, .stories.jsx, .stories.ts, .stories.tsx 등의 확장자를 사용해서 작성합니다.
src/
// 컴포넌트와 같이 관리
components/
Button/
Button.tsx
Button.stories.tsx
// src/stories 에서 모아서 관리
stories/
Header.stories.tsx
Footer.stories.tsx
스토리 파일들을 같은 디렉토리에 모아서 관리할 수도 있지만, 실제 컴포넌트와 같은 폴더에 파일을 작성해서 관리할 수도 있습니다!
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import { Button } from "@atom/index.tsx";
const meta = {
title: "Example/Button",
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: { ... },
args: { ... },
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Primary: Story = {
args: {
variant: "primary",
label: "Primary Button",
},
};
export const Outline: Story = {
args: {
variant: "outline",
label: "Outline Button",
},
};
export const Disabled: Story = {
args: {
variant: "disabled",
label: "Disabled Button",
},
};
위와 같이 Button 컴포넌트들에 대한 다양한 스토리(Primary, Outline, Disabled)를 정의할 수 있습니다.
좋은 스토리북 작성을 위해 몇가지 Best Practice에 대해 알아보겠습니다!
Best Practices란?
Best Practices는 특정 분야에서 일반적으로 권장되는 방법이나 절차를 의미합니다. 이는 오랜 시간 동안 축적된 경험과 연구를 바탕으로 최적의 결과를 얻기 위해 채택된 표준 방법론입니다. 소프트웨어 개발에서는 코드 품질, 효율성, 유지보수성 등을 높이기 위해 다양한 Best Practices를 따릅니다.
export default {
title: 'Components/Button',
component: Button,
}; ‘Components/Button’ 등 계층화된 이름을 사용함으로써, 스토리를 쉽게 탐색할 수 있게 하는 것이 좋습니다.export const Primary: Story = { ... }
export const Outline: Story = { ... }
export const Disabled: Story = { ... }
export const Small: Story = { ... }
export const Medium: Story = { ... }
export const Large: Story = { ... } 각 컴포넌트의 다양한 상태와 변형을 포함하도록 여러개의 스토리를 작성하는 것이 좋습니다.스토리북이 결국 컴포넌트를 보여주는 것이기 때문에, 컴포넌트 자체를 잘 설계하는 것이 중요합니다.
스토리북이 무엇인지, 왜 사용하는지, 어떤 장점이 있는지, 어떻게 설정하는지까지 알아봤습니다
그럼 이제 프로젝트에 적용만 하면되는데,,,
설치 방법 및 적용은 실습을 기대해주세요 ㅎㅎ
스토리북!!!
항상 개발할 때 부랴부랴 일정이 바빠서 꼭 잘 사용하고 싶었던 기술인데 지금까지 몇 번 경험을 못해봤네요.. ㅠㅠ
스토리북 => 컴포넌트를 보여주는 것이기 때문에, 곧 컴포넌트를 더 잘 설계하는 것이 정말 중요하고, 협업을 할 때 특히 공통 컴포넌트와 같은 것들을 쉽게 볼 수 있는 것이 정말 큰 장점이네요!
태승님이 언급한대로 더 모듈화되고 재사용 가능한 컴포넌트를 설계하는 것에 너무 동감합니다!
아티클 잘 읽있었습니다! 고생하셨습니다! 🥧
스토리북.. 한 번 깔짝하고 사용해본 경험이 있는데, 조금 신선한 충격이었던 것 같습니다. 그래서 조금 더 심도있게 배워보고 싶다는 생각이였는데, 이렇게 아티클을 통해 자세히 알려주시다니 너무 좋은 것 같습니다 ! 스토리북을 안쓴다면 내가 만든 컴포넌트를 App에 집어넣고 로컬에서 일일히 확인해야하는 단점이 있지만, 스토리북을 사용한다면 이런 과정 없이 해당 로컬에서 바로 확인할 수 있다는 장점이 있는 것 같습니다.
UI 테스트를 위해 스토리북을 활용하여 아주 간편하게 컴포넌트의 UI를 점검할 수 있는 것이 스토리북의 최대 장점인 것 같습니다. 태승님이 준비하신 실습을 통해 좀 더 깊게 배워보고 싶습니다.
스토리북을 한 번도 사용해보지 않은 입장으로써 너무 유익한 아티클이었습니다. 개인적으로 3주차 과제까지의 과제를 대략적으로 코드리뷰하러 돌아다녀 본 결과, 주용님이 최대한 스토리북처럼 느껴지게 코드를 작성한다는 느낌을 받았습니다.
UI관련된 부분을 미리 테스트 해볼 수 있다는게 너무 큰 장점인 것 같아요. 스토리북을 웹잼단에서 도입해보는게 좋은 선택일지 궁금해지는 밤입니다. 스토리북은 본격적인 개발이 진행되기 전에만 도입되어야 하는 라이브러리일까요?
러닝커브가 높지 않다면 꼭 도입해서 사용해보고 싶네요.
저는 사실 스토리북을 처음 알게 되었습니다. 컴포넌트 설계와 팀 협업에 큰 이점을 제공한다는 것이 신기한 것 같습니다! 또, 디자이너와의 협업까지도 실시간으로 피드백을 주고받으며 소통할 수 있다는 점이 정말 유용하네요. 스토리북 덕분에 컴포넌트의 다양한 상태를 쉽게 확인하고, 더 모듈화된 컴포넌트를 설계할 수 있다는 점이 인상깊었습니다. 이번 스터디 주제인 TDD와 스토리북에 대해 실습하는 것이 기대됩니다! 유익한 정보를 공유해주셔서 감사합니다 :)
스토리북에 대해서 들어보긴 했지만 사용하면 어떤 점이 좋은지, 그리고 무엇을 하는 것인가를 몰랐었는데 이번 아티클에 아주 명료하게 되어 있어서 잘 이해할 수 있었습니다. 확실히 버튼의 예시로 보여주신 것 처럼 스토리 북이 있으면 하나하나 테스트 코드 작성없이 한눈에 파악을 할 수 있어서 개발을 하는데 효율이 올라갈 것 같네요. 그리고 스토리북을 사용하면 더 모듈화되고 재사용성 있는 컴포넌트를 만드는 것에 대해 노력하게 된다는 의견도 옳다고 생각합니다. 스토리 작성 예시를 보니 모든 컴포넌트에 한해서가 아니라 재사용성이 높은 컴포넌트에 한해서는 진행하는 프로젝트에 스토리북을 사용해보고 싶다는 생각이 들었습니다. 아티클이 아니었다면 또 미뤄두었을 스토리북에 대해 접하게 해주셔서 감사합니다!!
Storybook은 독립적인 환경에서 컴포넌트를 그리게 되므로, 컴포넌트의 의존성, 데이터 처리 등에 대해 다시 검토할 수 있게 되고, 이를 통해 더 모듈화되고 재사용 가능한 컴포넌트를 설계할 수 있게 됩니다. 이 부분이 정말 인상 깊네요. 이런 부분에서도 도움이 되는지는 이번 아티클을 통해서 처음 알게되었어요. 저는 스토리북을 사용해본적이 없어서 어떤 상황에서 어느 정도 규모로 사용해야하는지 더 공부해봐야할 것 같습니다. 컴포넌트가 많을 때에는 어느정도까지 스토리북을 사용해야하는가에 대한 궁금증이 생겨요..! 다른 파트와 협업할 때 검토를 하는데에도 확실히 도움이 되겠군요..
재사용 가능한 컴포넌트를 설계하고 협업에 도움이 되는 스토리북 꼭 사용해보고싶습니다. 좋은 글 감사드려요!
우와 스토리북이 개발을 하는 데 있어 시각적인 도움을 줄 수 있다는 것 정도만 알고 있었는데 스토리북 사용의 이점이 이렇게 명시적으로 뚜렷하게 나타날 수 있음을 이제서야 알게 되었어요! 이렇게 컴포넌트 설계에 큰 이점을 가져다 줄 수 있다면 프로젝트 시에 같은 파트원끼리만이 아닌 디자인 파트 등 다른 파트와 협업하는 데 정말 용이하겠네요! 스토리북을 도입하지 않을 이유가 없겠어요… 🫢 덕분에 낯설었던 개념인 스토리북에 대해 많이 알아갑니다! 실습이 너무 기대돼요 :)