[ 살펴보기 ] Storybook - Configuration
![[ 살펴보기 ] Storybook - Configuration](https://cdn.hashnode.com/res/hashnode/image/upload/v1727877843128/ae3586c5-0353-4c08-9cbf-b694f083bde7.jpeg)
.storybook/main.ts 파일
npx storybook@latest init 명령을 통해 storybook을 설치했다면 .storybook 폴더에 main.ts 파일이 존재하는데 main.ts을 통해 story 파일의 위치 및 사용할 addon 또는 framework 관련 설정을 한다. main.ts 파일은 .storybook 폴더 안에 위치해야 하며 .storybook 폴더 역시 project의 root level에 위치해야 한다.
아래는 NextJS project에서 npx storybook@latest init을 통해 storybook을 세팅했을 때 생성되는 main.ts의 예제다.
import type { StorybookConfig } from "@storybook/nextjs";
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/nextjs",
options: {},
},
staticDirs: ["..\\public"]
};
export default config;
story config object에 설정할 수 있는 property는 다음과 같다.
stories : story 파일의 위치를 설정한다. 위치는 main.ts 파일의 위치를 기준으로 상대 경로로 지정한다. 위의 예제에서 src 폴더에 있는 모든 파일 중
.stories.가 포함된 파일이나.mdx확장자를 가진 파일을 story 파일로 인식한다.addons : storybook에 추가할 addon 리스트를 설정한다.
framework : 사용하는 framework에 따라 추가로 필요한 설정을 추가한다. 사용하는 framework마다 요구되는 설정사항이 다를 수 있으니 사용하는 framework storybook 관련 documentation을 참고한다.
staticDirs : static 파일을 관리하는 폴더의 경로를 설정한다.
typescirpt : typesciprt file과 관련된 설정을 한다.
core : Storybook 내부 기능에 대한 설정을 한다.
docs : Storybook에서 자동 생성하는 docs에 대한 설정을 한다.
feature : core 기능이 아닌 기타 추가 기능을 설정할 때 사용할 수 있다.
refs : Storybook 구성과 관련된 설정을 한다.
logLevel : Storybook의 log level을 설정할 수 있다.
webpackFinal : Stroybook은 default로 webpack을 build tool로 사용한다. Storybook과 관련된 webpack 세팅을 설정할 수 있다.
viteFinal : default 옵션인 webpack이 아닌 vite를 통해 storybook을 구성할 수 있다. vite 통해 storybook을 구성할 때 vite의 세팅을 설정한다.
env : Storybook 환경변수를 설정할 수 있다.
build : Storybook의 production build 관련 설정을 할 수 있다.
Storybook update
Stroybook은 최신버전으로 update 해야할 때 보다 편하게 작업을 수행할 수 있도록 다음 command를 지원한다.
npx storybook@latest upgrade;
위의 command는 storybook을 lateset version으로 update한다. latest version 뿐만 아니라 원하는 version을 지정하여 upgrade를 할수도 있다.
npx storybook@8.3.2 upgrade;
위의 예시처럼 upgrade command를 실행하면 project에서 사용하고 있는 storybook package를 지정한 version으로 update하고 그 외에 추가로 필요한 automigration 작업을 실행한다.
Integration with MUI
Storybook과 MUI를 함께 사용한다면 보다 나은 통합을 위해 다음과 같이 설정한다.
우선 @storybook/addon-themes package가 필요하므로 설치한다.
npm install @storybook/addon-themes
package를 설치한 다음 .storybook/main.ts 파일에 설치한 addon을 추가해준다.
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: [
...
"@storybook/addon-themes",
],
...
};
export default config;
그리고 MUI는 default font로 Roboto를 사용하고 Material Icons을 사용하므로 보다 나은 Storybook performance를 위해 이 둘을 설치하여 설정에 추가해준다.
npm install @fontsource/roboto @fontsource/material-icons
그리고 .storybook/preview.ts 파일에 아래와 같이 import 해준다.
import '@fontsource/roboto/300.css';
import '@fontsource/roboto/400.css';
import '@fontsource/roboto/500.css';
import '@fontsource/roboto/700.css';
import '@fontsource/material-icons';
...
그리고 같은 파일에 다음과 같이 MUI theme과 global CSS 관련 사항 역시 설정 해준다.
import "@fontsource/roboto/300.css";
import "@fontsource/roboto/400.css";
import "@fontsource/roboto/500.css";
import "@fontsource/roboto/700.css";
import "@fontsource/material-icons";
import type { Preview } from "@storybook/react";
import { CssBaseline, ThemeProvider } from "@mui/material";
import { withThemeFromJSXProvider } from "@storybook/addon-themes";
import { themeLight, themeDark } from "../src/theme";
const preview: Preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
...
},
decorators: [
withThemeFromJSXProvider({
themes: {
light: themeLight,
dark: themeDark,
},
defaultTheme: "light",
Provider: ThemeProvider,
GlobalStyles: CssBaseline,
}),
],
};
export default preview;
...
위의 예제에서 MUI에 theme에 사용되는 theme object가 src/theme.ts 파일에서 export 되고 있다고 가정한다.
// src/theme.ts
import { createTheme } from "@mui/material";
const themeLight = createTheme({ ... });
const themeDark = createTheme({ ... });
Stroybook을 통해 story의 args property와 argTypes을 통해 control panel에 component가 필요로 하는 props을 설정하지만 MUI component prop의 type을 활용하면 args property를 일일이 설정할 필요없이 component story의 args property를 설정할 수 있다.
Storybook이 MUI prop의 type을 이용하여 story의 args property를 추가 할 수 있도록 .storybook/main.ts 파일의 typescript property를 다음과 같이 수정한다.
import type { StorybookConfig } from "@storybook/nextjs";
const config: StorybookConfig = {
...
typescript: {
reactDocgen: "react-docgen-typescript",
reactDocgenTypescriptOptions: {
compilerOptions: {
allowSyntheticDefaultImports: false,
esModuleInterop: false,
},
shouldExtractLiteralValuesFromEnum: true,
shouldRemoveUndefinedFromOptional: true,
propFilter: (prop) =>
prop.parent
? !/node_modules\/(?!@mui)/.test(prop.parent.fileName)
: true,
},
},
};
export default config;
필자는 다음과 같이 MUI가 제공하는 Button의 property 중 4개만 선택하여 적용하고 있다.
import { ButtonProps, Button as MuiButton } from "@mui/material";
import React, { PropsWithChildren } from "react";
export type ButtonCompProps = Pick<
ButtonProps,
"variant" | "color" | "size" | "disabled"
> &
PropsWithChildren;
const Button = ({
children = "Button",
variant = "contained",
...props
}: ButtonCompProps) => {
return (
<MuiButton variant={variant} {...props}>
{children}
</MuiButton>
);
};
export default Button;
그리고 위의 component에 대한 story는 다음과 같다.
import type { Meta, StoryObj } from "@storybook/react";
import Button from "./Button";
const meta = {
title: "DesignSystem/Atom/Button/MuiButton",
component: Button,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
} satisfies Meta<typeof Button>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Contained: Story = {
args: {
variant: "contained",
},
};
export const Outlined: Story = {
args: {
variant: "outlined",
},
};
Component와 Story가 위와 같을 때 storybook을 확인해보면 우리가 Pick utility type을 통해 선택한 property가 아래와 같이 story의 control panel에 나타나는 것을 확인할 수 있다.

![[ 살펴보기 ] RDB - Relationships](https://cdn.hashnode.com/res/hashnode/image/upload/v1739711556668/48dc9e84-a621-42aa-9c9f-5fc5c436f0ec.jpeg)
![[ 살펴보기 ] MySQL - Data types](https://cdn.hashnode.com/res/hashnode/image/upload/v1739593589113/530f8704-4d27-42c9-a451-bb5c63150b99.jpeg)
![[ 살펴보기 ] TypeORM - Transactions, Migration](https://cdn.hashnode.com/res/hashnode/image/upload/v1739106042581/980b8133-61d4-406a-a026-65be9c28eace.jpeg)
![[ 살펴보기 ] TypeORM - Relations](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666874402/b688bd0b-b6bb-4f43-87d8-c1b46b59f1b7.jpeg)
![[ 살펴보기 ] TypeORM - Basics](https://cdn.hashnode.com/res/hashnode/image/upload/v1738666803591/bef5df17-7dc7-4123-ae55-004d5042df39.jpeg)