목차
개요
이번 블로그 포스트에서는 TypeScript를 기반으로 하는 Next.js 프로젝트에서 Storybook를 사용하여 컴포넌트 주도 개발(Component Driven Development)을 해 봅시다.
여기서 소개한 소스코드는 아래에 링크를 통해 확인할 수 있습니다.
블로그 리스트
이 블로그 포스트는 시리즈로 제작되었습니다. 다음은 Next.js의 시리즈 리스트입니다.
- [Next.js] 시작하기
- [Next.js] TypeScript
- [Next.js] Prettier
- [Next.js] 절대 경로로 컴포넌트 추가
- [Next.js] 테스트
- [Next.js] Storybook
- [Next.js] Storybook 배경색 변경
- [Next.js] 다국어 지원
- [Next.js] MUI
TypeScript 기반 Next.js 프로젝트 생성
TypeScript가 적용된 Next.js에서 Storybook을 사용하기 위해, 다음 명령어를 실행하여 TypeScript가 적용된 Next.js 프로젝트를 생성합니다.
npx create-next-app --typescript start-storybook
Storybook 설치
TypeScript가 적용된 Next.js 프로젝트에서 Storybook을 사용하여 컴포넌트 주도 개발을 하기 위해서는 Storybook을 설치할 필요가 있습니다. 다음 명령어를 실행하여 Storybook을 설치합니다.
# cd start-storybook
npm install --save-dev sb
Storybook 초기화
Storybook을 사용하기 위해서는 Storybook을 초기화하여 필요한 라이브러리를 설치할 필요가 있습니다. 다음 명령어를 사용하여 Storybook을 초기화합니다.
npx sb init --builder webpack5
그럼 다음과 같이 자동으로 Storybook이 초기화 되는 것을 확인할 수 있습니다.
sb init - the simplest way to add a Storybook to your project.
• Detecting project type. ✓
There seems to be a Storybook already available in this project.
Apply following command to force:
sb init [options] -f
🔎 checking 'cra5'
🔎 checking 'webpack5'
🔎 checking 'angular12'
🔎 checking 'mainjsFramework'
Unable to find storybook main.js config, skipping
🔎 checking 'eslintPlugin'
마지막으로 다음과 같은 질문이 나옵니다.
? Do you want to run the 'eslintPlugin' fix on your project? › (y/N)
ESLint를 사용하여 코드를 검사하는 경우 y를 눌러 진행하고, 그렇지 않은 경우는 N을 눌러 진행합니다. 이 블로그에서는 y를 눌러 진행하였습니다.
그럼 다음과 같이 Storybook이 자동으로 필요한 라이브러리를 설치하고, Storybook을 실행하는 스크립트를 자동으로 작성된 것을 확인할 수 있습니다.

{
...
"scripts": {
...
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
...
"devDependencies": {
"@babel/core": "^7.17.7",
"@storybook/addon-actions": "^6.4.19",
"@storybook/addon-essentials": "^6.4.19",
"@storybook/addon-interactions": "^6.4.19",
"@storybook/addon-links": "^6.4.19",
"@storybook/builder-webpack5": "^6.5.0-beta.8",
"@storybook/manager-webpack5": "^6.5.0-beta.8",
"@storybook/react": "^6.4.19",
"@storybook/testing-library": "^0.0.9",
"babel-loader": "^8.2.3",
"eslint-plugin-storybook": "^0.5.7",
...
}
}
또한, 다음과 같이 Storybook을 사용하는 방법을 알려주기 위해, 샘플 코드가 함께 생성되는 것을 확인할 수 있습니다.
./.storybook/...:Storybook에 대한 설정 파일입니다../stories/...:Storybook의 샘플 코드입니다.
public 폴더 설정
Next.js의 public 폴더에 위치한 static 파일들(이미지)을 Storybook에서 인식하도록 하기 위해 scripts를 다음과 같이 수정합니다.
{
...
"scripts": {
...
"storybook": "start-storybook -p 6006 -s ./public",
"build-storybook": "build-storybook -s public"
},
...
}
Storybook 실행
이제 지금까지 설정한 Storybook을 실행하여, Storybook이 잘 설치되었는지 확인해 봅시다. 다음 명령어를 실행하여 Storybook을 실행합니다.
npm run storybook
그럼 브라우저에 http://localhost:6006/이 자동으로 열리며, 다음과 같은 화면을 확인할 수 있습니다.

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

해당 화면은 ./stories/Button.stories.tsx 파일이 표시된 화면입니다.
샘플 코드 확인
좀 더 자세히 알아보기 위해 샘플 코드를 확인해 봅시다. 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) => {
...
};
Button 컴포넌트는 primary, backgroundColor 등 다양한 Props를 가지고 있는 것을 확인할 수 있습니다. 다음으로 Storybook 파일(./stories/Button.stories.tsx)의 내용을 확인해 봅시다.
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof Button>;
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
export const Secondary = Template.bind({});
Secondary.args = {
label: 'Button',
};
export const Large = Template.bind({});
Large.args = {
size: 'large',
label: 'Button',
};
export const Small = Template.bind({});
Small.args = {
size: 'small',
label: 'Button',
};
우선, Storybook에 표시할 컴포넌트를 준비합니다.
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { Button } from './Button';
export default {
title: 'Example/Button',
component: Button,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof Button>;
const Template: ComponentStory<typeof Button> = (args) => <Button {...args} />;
...
argTypes의 backgroundColor에 control: 'color'을 설정하면, 다음과 같이 Storybook에서 색상을 선택할 수 있습니다.

그런 다음 화면에 표시할 Story를 작성합니다.
...
export const Primary = Template.bind({});
Primary.args = {
primary: true,
label: 'Button',
};
...
여기서 args에 Button 컴포넌트의 Props를 설정하여 다양한 Story를 만들 수 있습니다.
Storybook 설정
우선 Next.js의 globals.css를 Storybook에서도 사용할 수 있도록 설정할 필요가 있습니다. ./storybook/preview.js 파일을 열고 다음과 같이 수정합니다.
import '../styles/globals.css'
export const parameters = {
...
}
현재는 Storybook을 작성하기 위해서는 ./stories 폴더에 작성해야 합니다. 하지만, 보통 컴포넌트는 ./components 폴더를 생성하고 관리하게 됩니다.
이렇게 Storybook을 다른 폴더에서 작성하기 위해서는 ./.storybook/main.js 파일을 수정할 필요가 있습니다. ./.storybook/main.js 파일을 열고 다음과 같이 수정합니다.
module.exports = {
"stories": [
"../**/*.stories.mdx",
"../**/*.stories.@(js|jsx|ts|tsx)"
],
...
}
이제는 어떠한 폴더에서든 .stories.tsx 파일명을 가지면, Storybook이 이를 인식하여 화면에 표시하게 됩니다. 이를 확인하기 위해 ./components/SampleButton 폴더를 생성하고 다음 파일들을 복사합니다.
./stories/button.css>./components/SampleButton/index.css./stories/Button.stories.tsx>./components/SampleButton/index.stories.tsx./stories/Button.tsx>./components/SampleButton/index.tsx
그리고 ./components/SampleButton/index.tsx 파일을 열어서 다음과 같이 수정합니다.
...
import './index.css';
...
export const SampleButton = ({
...
}: ButtonProps) => {
...
};
그리고 ./components/SampleButton/index.stories.tsx 파일을 열어서 다음과 같이 수정합니다.
...
import { SampleButton } from '.';
...
export default {
title: 'Example/SampleButton',
component: SampleButton,
...,
} as ComponentMeta<typeof SampleButton>;
const Template: ComponentStory<typeof SampleButton> = (args) => (
<SampleButton {...args} />
);
...
Storybook의 설정을 변경하였으므로 이를 반영하기 위해, 현재 실행중인 Storybook을 종료하고 다시 실행합니다. Storybook이 다시 실행되면 다음과 같이 우리가 만든 SampleButton이 잘 표시되는 것을 확인할 수 있습니다.

완료
이번 블로그 포스트에서는 TypeScript를 기반으로 하는 Next.js 프로젝트에서 컴포넌트 주도 개발을 하기 위해, Storybook을 설정하는 방법에 대해서 알아보았습니다. 이제 앱을 개발할 때, Storybook을 보면서, 컴포넌트에 집중하여 개발할 수 있게 되었습니다.
제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!
앱 홍보
Deku가 개발한 앱을 한번 사용해보세요.Deku가 개발한 앱은 Flutter로 개발되었습니다.관심있으신 분들은 앱을 다운로드하여 사용해 주시면 정말 감사하겠습니다.














![[심통]현장에서 바로 써먹는 리액트 with 타입스크립트 : 리액트와 스토리북으로 배우는 컴포넌트 주도 개발, 심통](https://img1c.coupangcdn.com/image/affiliate/banner/7cba8cb0601eebaf88a17a0c3cf65a63@2x.jpg)