목차
개요
이번 블로그 포스트에서는 TypeScript
를 기반으로 하는 Next.js
프로젝트에서 Storybook
를 사용하여 컴포넌트 주도 개발(Component Driven Development)을 해 봅시다.
이번 블로그 포스트에서는 Storybook
의 V7
버전(next
)을 사용하는 방법에 대해서 알아볼 예정입니다. V6
버전을 사용하는 방법에 대해서는 다음 링크를 참고하시기 바랍니다.
여기서 소개한 소스코드는 아래에 링크를 통해 확인할 수 있습니다.
TypeScript 기반 Next.js 프로젝트 생성
TypeScript
가 적용된 Next.js
에서 Storybook
을 사용하기 위해, 다음 명령어를 실행하여 TypeScript
가 적용된 Next.js
프로젝트를 생성합니다.
npx create-next-app --typescript start-storybook-v7
Storybook 설치
TypeScript
가 적용된 Next.js
프로젝트에서 Storybook
을 사용하여 컴포넌트 주도 개발을 하기 위해서는 Storybook
을 설치할 필요가 있습니다. 다음 명령어를 실행하여 Storybook
을 설치합니다.
# cd start-storybook-v7
npm install --save-dev [email protected]
Storybook 초기화
Storybook
을 사용하기 위해서는 Storybook
을 초기화하여 필요한 라이브러리를 설치할 필요가 있습니다. 다음 명령어를 사용하여 Storybook
을 초기화합니다.
npx [email protected] init
그럼 다음과 같이 자동으로 Storybook
이 초기화 되는 것을 확인할 수 있습니다.
storybook init - the simplest way to add a Storybook to your project.
• Detecting project type. ✓
• Adding Storybook support to your "Next" app
added 318 packages, and audited 1125 packages in 54s
226 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
. ✓
• Preparing to install dependencies. ✓
마지막으로 다음과 같은 질문이 나옵니다.
? Do you want to run the 'eslintPlugin' migration on your project? › (Y/n)
ESLint
를 사용하여 코드를 검사하는 경우 y
를 눌러 진행하고, 그렇지 않은 경우는 n
을 눌러 진행합니다. 이 블로그에서는 y
를 눌러 진행하였습니다.
그럼 다음과 같이 Storybook
이 자동으로 필요한 라이브러리를 설치하고, Storybook
을 실행하는 스크립트를 자동으로 작성된 것을 확인할 수 있습니다.

{
...
"scripts": {
...
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
...
"devDependencies": {
"@storybook/addon-essentials": "^7.0.0-rc.8",
"@storybook/addon-interactions": "^7.0.0-rc.8",
"@storybook/addon-links": "^7.0.0-rc.8",
"@storybook/blocks": "^7.0.0-rc.8",
"@storybook/nextjs": "^7.0.0-rc.8",
"@storybook/react": "^7.0.0-rc.8",
"@storybook/testing-library": "^0.0.14-next.1",
"eslint-plugin-storybook": "^0.6.11",
"storybook": "^7.0.0-rc.8"
...
}
}
또한, 다음과 같이 Storybook
을 사용하는 방법을 알려주기 위해, 샘플 코드가 함께 생성되는 것을 확인할 수 있습니다.
./.storybook/...
:Storybook
에 대한 설정 파일입니다../stories/...
:Storybook
의 샘플 코드입니다.
ESLint
를 사용하도록 설정하였으므로, .eslintrc.json
파일을 열면 다음과 같이 변경된 것을 확인할 수 있습니다.
{
"extends": [
"next/core-web-vitals",
"plugin:storybook/recommended"
]
}
public 폴더 설정
Next.js
의 public
폴더에 위치한 static
파일들(이미지)을 Storybook
에서 인식하도록 하기 위해 main.ts
파일을 열고 다음과 같이 수정합니다.
import type { StorybookConfig } from '@storybook/nextjs'
const config: StorybookConfig = {
...
docs: {
autodocs: 'tag',
},
staticDirs: ['../public'],
}
export default config
Storybook 실행
이제 지금까지 설정한 Storybook
을 실행하여, Storybook
이 잘 설치되었는지 확인해 봅시다. 다음 명령어를 실행하여 Storybook
을 실행합니다.
npm run storybook
그럼 브라우저에 http://localhost:6006/
이 자동으로 열리며, 다음과 같은 화면을 확인할 수 있습니다.

해당 화면은 ./stories/Introduction.mdx
파일이 표시된 화면입니다.
Storybook 확인
실행된 Storybook
의 왼쪽 메뉴의 Button > Primary
를 선택하면 다음과 같은 화면을 볼 수 있습니다.

해당 화면은 ./stories/Button.stories.ts
파일이 표시된 화면입니다.
샘플 코드 확인
좀 더 자세히 알아보기 위해 샘플 코드를 확인해 봅시다. Button
컴포넌트(./stories/Button.tsx
)는 다음과 같습니다.
import React from 'react';
import './button.css';
interface ButtonProps {
primary?: boolean;
backgroundColor?: string;
size?: 'small' | 'medium' | 'large';
label: string;
onClick?: () => void;
}
export const Button = ({
primary = false,
size = 'medium',
backgroundColor,
label,
...props
}: ButtonProps) => {
const mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
return (
<button
type="button"
className={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
{...props}
>
{label}
<style jsx>{`
button {
background-color: ${backgroundColor};
}
`}</style>
</button>
);
};
Button
컴포넌트는 primary
, backgroundColor
등 다양한 Props
를 가지고 있는 것을 확인할 수 있습니다. 다음으로 Storybook
파일(./stories/Button.stories.ts
)의 내용을 확인해 봅시다.
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Example/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
backgroundColor: {
control: 'color',
},
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = {
args: {
primary: true,
label: 'Button',
},
};
export const Secondary: Story = {
args: {
label: 'Button',
},
};
export const Large: Story = {
args: {
size: 'large',
label: 'Button',
},
};
export const Small: Story = {
args: {
size: 'small',
label: 'Button',
},
};
우선, Storybook
의 화면 구성에 필요한 정보를 준비합니다.
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
title: 'Example/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
backgroundColor: {
control: 'color',
},
},
};
export default meta;
type Story = StoryObj<typeof Button>;
...
meta
는 Storybook
에 표시할 기본 정보를 설정합니다. meta
에 설정한 title
은 Storybook
의 왼쪽 메뉴에 표시될 이름을 나타내며 /
를 통해 그룹을 만들 수 있습니다. 예제 코드에서는 Example
그룹 하위에 Button
이라는 이름으로 표시되는 것을 확인할 수 있습니다.

meta
의 component
는 이 Storybook
에 표시할 컴포넌트를 지정합니다. 예제에서는 Button
컴포넌트를 지정했습니다.
tags: ['autodocs']
는 자동으로 문서(Document)를 작성해주는 새로운 기능입니다. 이 값을 설정하면 위에 그림에서처럼 Example/Button
메뉴 하위에 Docs
가 자동으로 생성되는 것을 확인할 수 있으며, 여기서 Storybook
파일에 작성한 내용을 문서 형태로 확인할 수 있습니다.
이렇게 화면 구성에 필요한 정보를 설정하였다면, 이제 실제로 화면에 표시될 Story
를 작성합니다. 다음과 같이 컴포넌트의 Props
들을 설정하거나 변경하는 것으로 Story
를 작성할 수 있습니다.
...
export const Primary: Story = {
args: {
primary: true,
label: 'Button',
},
};
export const Secondary: Story = {
args: {
label: 'Button',
},
};
export const Large: Story = {
args: {
size: 'large',
label: 'Button',
},
};
export const Small: Story = {
args: {
size: 'small',
label: 'Button',
},
};
Storybook 설정
현재는 Storybook
을 작성하기 위해서는 ./stories
폴더에 작성해야 합니다. 하지만, 보통 컴포넌트는 ./components
폴더를 생성하고 관리하게 됩니다.
이렇게 Storybook
을 다른 폴더에서 작성하기 위해서는 ./.storybook/main.ts
파일을 수정할 필요가 있습니다. ./.storybook/main.ts
파일을 열고 다음과 같이 수정합니다.
import type { StorybookConfig } from '@storybook/nextjs';
const config: StorybookConfig = {
stories: [
'../@(stories|components)/**/*.mdx',
'../@(stories|components)/**/*.stories.@(js|jsx|ts|tsx)',
],
...
};
...
이제는 stories
폴더 이외에 components
폴더에서도 .stories.ts
파일명을 가지면, Storybook
이 이를 인식하여 화면에 표시하게 됩니다. 이를 확인하기 위해 ./components/SampleButton
폴더를 생성하고 다음 파일들을 복사합니다.
./stories/button.css
>./components/SampleButton/index.css
./stories/Button.stories.ts
>./components/SampleButton/index.stories.ts
./stories/Button.tsx
>./components/SampleButton/index.tsx
그리고 ./components/SampleButton/index.tsx
파일을 열어서 다음과 같이 수정합니다.
...
import './index.css';
...
export const SampleButton = ({
...
}: ButtonProps) => {
...
};
그리고 ./components/SampleButton/index.stories.ts
파일을 열어서 다음과 같이 수정합니다.
...
import { SampleButton } from '.';
const meta: Meta<typeof SampleButton> = {
title: 'Sample/Button',
component: SampleButton,
...
};
export default meta;
type Story = StoryObj<typeof SampleButton>;
...
Storybook
의 설정을 변경하였으므로 이를 반영하기 위해, 현재 실행중인 Storybook
을 종료하고 다시 실행합니다. Storybook
이 다시 실행되면 다음과 같이 우리가 만든 SampleButton
이 잘 표시되는 것을 확인할 수 있습니다.

완료
이번 블로그 포스트에서는 TypeScript
를 기반으로 하는 Next.js
프로젝트에서 컴포넌트 주도 개발을 하기 위해, Storybook V7
을 설정하는 방법에 대해서 알아보았습니다. 이전 버전에 비해 많이 편리해지고 좀 더 직관적으로 변경된 것을 확인할 수 있었습니다. 이전 버전의 Storybook
을 설정하고 사용하는 방법에 대해서는 다음 링크를 참고하시기 바랍니다.
제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!
앱 홍보
Deku
가 개발한 앱을 한번 사용해보세요.Deku
가 개발한 앱은 Flutter로 개발되었습니다.관심있으신 분들은 앱을 다운로드하여 사용해 주시면 정말 감사하겠습니다.