blog

Storybook 도입 검토: 장단점과 Vue 버튼 컴포넌트 적용기

Front-end / Tooling#Storybook#Vue#디자인 시스템#컴포넌트 문서화

Vue 프로젝트에 Storybook 도입을 검토하면서 정리한 장단점과 샘플 적용 결과다.

Storybook이란

UI 컴포넌트를 앱과 분리된 환경에서 개발·문서화·테스트할 수 있는 도구다. Vue, React, Angular 등 대부분의 프레임워크를 지원한다.

장점

  1. 컴포넌트 독립 개발: 라우팅, API, 전역 상태 없이 컴포넌트 하나만 띄워 UI를 확인할 수 있다. 특정 상태(빈 목록, 에러, 긴 텍스트)를 재현하려고 페이지를 조작할 필요가 없다.
  2. 자동 문서화: props, events, slots 정보로 문서(Docs)를 생성하고, Controls 패널에서 props를 바꿔 가며 바로 확인할 수 있다.
  3. 디자인 협업: @storybook/addon-designs로 Figma 시안을 스토리 옆에 띄워 비교할 수 있다. 정적 사이트로 배포하면 디자이너·기획자도 링크로 확인하고 피드백할 수 있다.
  4. UI 회귀 테스트 기반: 스토리를 그대로 시각적 회귀 테스트(Chromatic 등)나 interaction test에 사용할 수 있다.
  5. 재사용성과 일관성: 프로젝트의 공통 컴포넌트 목록이 한눈에 보이므로, 새로 만들기 전에 기존 컴포넌트를 찾기 쉽다.
  6. 온보딩: 새 팀원이 스토리만 보고 컴포넌트 사용법을 파악할 수 있다.

단점

  1. 초기 세팅과 학습 비용: 프로젝트의 alias, 전역 스타일, 플러그인(i18n, Pinia 등)을 Storybook 설정(.storybook/main.ts, preview.ts)에 맞춰 줘야 한다. slot, emit, v-model이 많은 컴포넌트는 스토리 작성이 번거롭다.
  2. 개발 의존성과 별도 빌드: 앱 번들 크기에는 영향을 주지 않지만, devDependencies가 크게 늘고 Storybook 전용 빌드·배포 파이프라인이 추가된다.
  3. 실제 환경과의 차이: provide/inject, 라우터, 스토어가 필요한 컴포넌트는 decorator나 mock을 따로 구성해야 하고, 실제 앱과 동작이 다를 수 있다.
  4. 유지보수 비용: 컴포넌트를 바꿀 때 스토리도 함께 고쳐야 한다. 관리되지 않는 스토리는 오히려 잘못된 문서가 된다.

샘플 적용: 공통 버튼 컴포넌트

스타일 props(type, color, width, height, padding)가 많은 공통 버튼에 먼저 적용했다.

// CommonBtn.stories.ts
import type { Meta, StoryObj } from '@storybook/vue3';
import CommonBtn from './CommonBtn.vue';

const meta = {
  title: 'Common/CommonBtn',
  component: CommonBtn,
  argTypes: {
    type: { control: 'select', options: ['filled', 'outlined', 'textLink'] },
  },
} satisfies Meta<typeof CommonBtn>;

export default meta;
type Story = StoryObj<typeof meta>;

export const EditButton: Story = {
  name: '수정 버튼',
  render: (args) => ({
    components: { CommonBtn },
    setup: () => ({ args }),
    template: '<CommonBtn v-bind="args">수정</CommonBtn>',
  }),
  args: {
    type: 'outlined',
    color: 'lightGray',
    width: '45px',
    height: '28px',
    padding: '8px 10px',
    disabled: false,
  },
};

export const ViewButton: Story = {
  name: '열람 버튼',
  render: EditButton.render,
  args: {
    type: 'outlined',
    color: 'secondary',
    height: '28px',
    padding: '4px 8px',
  },
};

스토리 export 이름은 영문으로 두고 화면 표시 이름은 name으로 지정하면, 도구 호환성과 가독성을 함께 챙길 수 있다.

기대 효과

항목효과
빠른 variation 확인props만 바꿔 다양한 버튼 조합을 바로 확인
시안 비교Figma 시안과 나란히 비교(designs addon)
테스트·디버깅 간소화페이지 로직 없이 렌더링 상태만 검증