Skip to main content

Command Palette

Search for a command to run...

[ 살펴보기 ] Storybook - Configuration

Published
4 min readView as Markdown
[ 살펴보기 ] Storybook - Configuration
C

A developer living in Busan, Korea

.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에 나타나는 것을 확인할 수 있다.

More from this blog

[ 살펴보기 ] TypeORM - Transactions, Migration

Transation Database 종류에 따라 detail한 부분은 차이점이 조금씩 있겠지만 각 sql statement는 개별적인 transaction block을 통해 실행되며 Database 설정에 따라 sql statement의 실행 결과가 자동으로 commit되어 영구히 적용되거나 commit을 직접 실행하기 전까지는 영구히 적용되지 않을 수 있다. 대부분의 경우 default로 sql statement 실행 결과가 자동으로 comm...

Feb 9, 20256 min read
[ 살펴보기 ] TypeORM - Transactions, Migration

Dev Diary

184 posts