Files
2nd/10_Wiki/Topics/Coding/Frontend_Storybook_Modern.md
T
2026-05-10 22:08:15 +09:00

6.3 KiB

id, title, category, status, source_trust_level, verification_status, created_at, updated_at, tags, tech_stack, applied_in, aliases
id title category status source_trust_level verification_status created_at updated_at tags tech_stack applied_in aliases
frontend-storybook-modern Storybook 9 — component dev / test / docs Coding draft B conceptual 2026-05-09 2026-05-09
frontend
storybook
vibe-coding
language applicable_to
TS
Frontend
Storybook 9
CSF 3
MDX
Chromatic
visual test
component library
design system

Storybook Modern (9)

Component 의 isolated dev + test + docs. CSF 3 (component story format), MDX, Chromatic visual test.

📖 핵심 개념

  • 매 component 가 isolated story.
  • Variant (default, error, loading) 가 visible.
  • Visual test (Chromatic).
  • Design system 친화.

💻 코드 패턴

Setup

npx storybook@latest init

CSF 3 (modern)

// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  component: Button,
  args: { children: 'Click me' },
  argTypes: {
    variant: { control: 'select', options: ['primary', 'secondary'] },
  },
};
export default meta;

type Story = StoryObj<typeof Button>;

export const Primary: Story = {
  args: { variant: 'primary' },
};

export const Secondary: Story = {
  args: { variant: 'secondary' },
};

export const Disabled: Story = {
  args: { disabled: true },
};

→ Args + render = story.

Interaction (play function)

import { userEvent, within, expect } from '@storybook/test';

export const ClickAction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const btn = canvas.getByRole('button');
    
    await userEvent.click(btn);
    await expect(btn).toHaveTextContent('Clicked');
  },
};

→ Story 가 test 도. Storybook UI 에서 step replay.

MDX (docs + story)

import { Meta, Story } from '@storybook/blocks';
import { Button } from './Button';

<Meta title='Button' component={Button} />

# Button

A primary button component.

## Variants

<Canvas>
  <Story name='Primary'>
    <Button variant='primary'>Primary</Button>
  </Story>
</Canvas>

## API

<ArgTypes />

→ Markdown + component embed.

Chromatic (visual regression)

npm i -D chromatic
npx chromatic --project-token=...

→ 매 PR 이 visual diff. Approve / reject.

Test runner

npm i -D @storybook/test-runner
npx test-storybook

→ 매 story 의 play 가 test. Headless run.

Mock (MSW)

import { http, HttpResponse } from 'msw';

export const Loaded: Story = {
  parameters: {
    msw: {
      handlers: [
        http.get('/api/users', () => HttpResponse.json([{ name: 'Alice' }])),
      ],
    },
  },
};

→ Real-like data.

Theme / decorator

const meta: Meta = {
  decorators: [
    (Story) => (
      <ThemeProvider theme={theme}>
        <Story />
      </ThemeProvider>
    ),
  ],
};

Args + controls

const meta: Meta<typeof Avatar> = {
  argTypes: {
    src: { control: 'text' },
    size: { control: { type: 'range', min: 16, max: 128, step: 8 } },
    variant: { control: 'select', options: ['circle', 'square'] },
  },
};

→ Storybook UI 에서 live tweak.

Auto-docs

const meta: Meta = {
  tags: ['autodocs'],
};

Docs tab 자동 생성 (props + variant).

Vite

// .storybook/main.ts
const config: StorybookConfig = {
  stories: ['../src/**/*.stories.@(ts|tsx|mdx)'],
  framework: { name: '@storybook/react-vite', options: {} },
  addons: ['@storybook/addon-essentials', '@storybook/addon-a11y'],
};

→ Vite 친화 (빠른).

a11y addon

npm i -D @storybook/addon-a11y

→ 매 story 가 axe 검증.

Build (deploy)

npm run build-storybook
# → static-storybook/ 에 deploy.

→ Vercel / Netlify / GitHub Pages.

Use case

- Design system (Bento, Radix UI examples).
- Component library showcase.
- Cross-team review.
- QA reproduction.
- Visual regression.
- Onboarding (이 component 가 무엇).

vs Histoire / Ladle / React Cosmos

Histoire: Vue 친화.
Ladle: lighter, faster.
React Cosmos: legacy.
Storybook: 가장 mature.

→ Storybook 가 default.

Performance

Storybook 9: 빠름 (Vite default).
큰 codebase: 1000+ story 가 OK.

→ 매 story file 가 lazy load.

Production tips

- 매 component 의 매 variant.
- Edge case (loading, error, empty).
- Long content (truncation).
- Different size / theme.
- A11y test 항상.
- Visual diff CI gate.

CI integration

- run: npm run build-storybook
- run: npx test-storybook --url http://localhost:6006
- run: npx chromatic

Composition (multi-storybook)

// .storybook/main.ts
const config = {
  refs: {
    'design-system': { url: 'https://design.example.com' },
    'component-library': { url: 'https://components.example.com' },
  },
};

→ 다른 storybook 가 1 navigation.

Args from URL

?args=variant:primary;size:lg

→ Bookmark / share.

Custom addon

// addon-my-feature/manager.ts
import { addons, types } from '@storybook/manager-api';

addons.register('my-addon', () => {
  addons.add('my-addon/panel', {
    type: types.PANEL,
    title: 'My Panel',
    render: ({ active }) => <div>Custom UI</div>,
  });
});

LLM 도움

- Story generation (component → variant).
- Visual diff explanation.
- A11y violation fix.

함정

- 모든 story 가 매 변경 = Chromatic cost.
- Story 가 stale (component 변경 후 안 update).
- Decorator 가 prod 가 다른 (theme).
- Args 가 너무 많음 = noisy.
- Build 가 slow (큰 codebase).

🤔 의사결정 기준

작업 추천
Component dev Storybook
Visual test Chromatic + Storybook
Design system Storybook + composition
Vue Histoire / Storybook
작은 / 빠름 Ladle
Documentation MDX + autodocs

안티패턴

  • Story 안 maintain: stale.
  • No edge case: production 가 first 진실.
  • Storybook + Cypress 둘 다 component test: redundant.
  • No visual diff: silent regression.
  • No a11y test: accessibility 깨짐.

🤖 LLM 활용 힌트

  • CSF 3 가 modern.
  • Chromatic + Storybook 가 visual test.
  • Play function 가 interaction test.
  • a11y addon 항상.

🔗 관련 문서