자동 문서 생성 (Auto-Docs)

TypeScript와 JSDoc을 활용하여 컴포넌트 문서를 자동으로 생성합니다.

← Storybook 가이드로 돌아가기

📚 Auto-Docs란?

Storybook은 TypeScript 타입과 JSDoc 주석을 분석하여 Props 테이블, 설명, 예제를 포함한 문서를 자동으로 생성합니다.

자동 생성

타입 정보 기반

항상 최신

코드와 동기화

노력 최소

한 번 설정으로 완료

⚡ Auto-Docs 활성화

Story에 태그 추가

const meta: Meta<typeof Button> = {
  title: 'UI/Button',
  component: Button,
  tags: ['autodocs'], // 👈 이것만 추가!
};

export default meta;

전역 설정 (.storybook/preview.ts)

export const parameters = {
  docs: {
    autodocs: 'tag', // 또는 true
  },
};

🎯 TypeScript로 완벽한 문서 생성

1단계: 타입 정의

// Button.tsx
export interface ButtonProps {
  /**
   * 버튼에 표시될 텍스트
   */
  children: React.ReactNode;
  
  /**
   * 버튼의 시각적 스타일
   * @default 'primary'
   */
  variant?: 'primary' | 'secondary' | 'danger' | 'ghost';
  
  /**
   * 버튼의 크기
   * @default 'medium'
   */
  size?: 'small' | 'medium' | 'large';
  
  /**
   * 비활성화 상태 여부
   * 비활성화되면 클릭할 수 없고 시각적으로 구분됩니다.
   * @default false
   */
  disabled?: boolean;
  
  /**
   * 전체 너비를 차지할지 여부
   * @default false
   */
  fullWidth?: boolean;
  
  /**
   * 로딩 중 표시 여부
   * 로딩 중에는 자동으로 disabled 상태가 됩니다.
   * @default false
   */
  loading?: boolean;
  
  /**
   * 아이콘 (왼쪽)
   * @example <Icon name="plus" />
   */
  leftIcon?: React.ReactNode;
  
  /**
   * 아이콘 (오른쪽)
   */
  rightIcon?: React.ReactNode;
  
  /**
   * 클릭 이벤트 핸들러
   */
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  
  /**
   * 버튼 타입
   * @default 'button'
   */
  type?: 'button' | 'submit' | 'reset';
  
  /**
   * ARIA 레이블
   * 접근성을 위해 명확한 설명 제공
   */
  'aria-label'?: string;
  
  /**
   * 테스트 ID
   * @internal
   */
  testId?: string;
}

export const Button: React.FC<ButtonProps> = ({
  children,
  variant = 'primary',
  size = 'medium',
  disabled = false,
  fullWidth = false,
  loading = false,
  leftIcon,
  rightIcon,
  onClick,
  type = 'button',
  'aria-label': ariaLabel,
  testId,
}) => {
  // 구현...
};

2단계: Story 작성

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

/**
 * Button 컴포넌트는 사용자 액션을 트리거하는 기본 UI 요소입니다.
 * 
 * ## 사용 가이드
 * - Primary: 주요 액션 (저장, 제출 등)
 * - Secondary: 보조 액션 (취소, 뒤로 등)
 * - Danger: 위험한 액션 (삭제, 초기화 등)
 * - Ghost: 최소한의 시각적 강조
 * 
 * ## 접근성
 * - 키보드 탐색 지원 (Tab, Enter, Space)
 * - ARIA 레이블 지원
 * - 색상 대비 WCAG AA 준수
 */
const meta: Meta<typeof Button> = {
  title: 'Components/Button',
  component: Button,
  tags: ['autodocs'], // 자동 문서화 활성화
  parameters: {
    docs: {
      description: {
        component: '이 컴포넌트는 모든 플랫폼에서 일관된 버튼 경험을 제공합니다.',
      },
    },
  },
  argTypes: {
    variant: {
      control: 'select',
      description: '버튼 스타일 변형',
      table: {
        type: { summary: "'primary' | 'secondary' | 'danger' | 'ghost'" },
        defaultValue: { summary: 'primary' },
      },
    },
    size: {
      control: 'radio',
      options: ['small', 'medium', 'large'],
    },
    disabled: {
      control: 'boolean',
    },
    loading: {
      control: 'boolean',
      description: '로딩 상태일 때 spinner가 표시됩니다.',
    },
    onClick: {
      action: 'clicked',
    },
  },
};

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

/**
 * 기본 Primary 버튼입니다.
 * 가장 중요한 액션에 사용하세요.
 */
export const Primary: Story = {
  args: {
    children: 'Primary Button',
    variant: 'primary',
  },
};

/**
 * Secondary 버튼은 보조 액션에 적합합니다.
 */
export const Secondary: Story = {
  args: {
    children: 'Secondary Button',
    variant: 'secondary',
  },
};

/**
 * 삭제나 초기화 같은 위험한 액션에 사용합니다.
 */
export const Danger: Story = {
  args: {
    children: 'Delete',
    variant: 'danger',
  },
  parameters: {
    docs: {
      description: {
        story: '사용자에게 경고 메시지를 먼저 표시하는 것이 좋습니다.',
      },
    },
  },
};

/**
 * 아이콘과 함께 사용하는 예제
 */
export const WithIcons: Story = {
  args: {
    children: 'Add Item',
    leftIcon: <span>➕</span>,
  },
};

/**
 * 비동기 작업 중 로딩 상태
 */
export const Loading: Story = {
  args: {
    children: 'Loading...',
    loading: true,
  },
};
✅ 결과: Storybook이 자동으로 다음을 생성합니다:
  • • Props 테이블 (타입, 기본값, 설명)
  • • 컴포넌트 설명
  • • Story별 설명
  • • 코드 예제
  • • Controls 패널

📝 JSDoc 태그 활용

@default
@default 'primary'

기본값 명시

@deprecated
@deprecated Use newProp instead

더 이상 사용 안 함

@example
@example <Icon name="check" />

사용 예제

@internal
@internal

내부 전용 (문서 제외)

@see
@see https://example.com

참고 링크

⚙️ Docs 커스터마이징

// .storybook/preview.ts
import { DocsContainer } from '@storybook/blocks';

export const parameters = {
  docs: {
    // 테마
    theme: themes.dark,
    
    // 커스텀 컨테이너
    container: DocsContainer,
    
    // Props 테이블 설정
    extractArgTypes: (component) => {
      // 커스텀 로직
    },
    
    // 소스 코드 포맷
    source: {
      language: 'tsx',
      format: true,
    },
    
    // 캔버스 설정
    canvas: {
      sourceState: 'shown', // 기본으로 표시
    },
  },
};

// Story별 커스터마이징
export const Advanced: Story = {
  parameters: {
    docs: {
      description: {
        story: '고급 사용 예제',
      },
      source: {
        code: `
<Button
  variant="primary"
  size="large"
  onClick={handleClick}
>
  Custom Code
</Button>
        `,
      },
    },
  },
};

🔧 복잡한 타입 문서화

// 유니온 타입
export type ButtonVariant = 
  | 'primary' 
  | 'secondary' 
  | 'danger' 
  | 'ghost';

// 제네릭 타입
export interface SelectProps<T = string> {
  /**
   * 선택 가능한 옵션들
   */
  options: Array<{
    /** 옵션 값 */
    value: T;
    /** 표시될 레이블 */
    label: string;
    /** 비활성화 여부 */
    disabled?: boolean;
  }>;
  
  /**
   * 현재 선택된 값
   */
  value?: T;
  
  /**
   * 값 변경 핸들러
   */
  onChange?: (value: T) => void;
}

// 객체 타입
export interface Theme {
  /**
   * 색상 팔레트
   */
  colors: {
    /** 주요 색상 */
    primary: string;
    /** 보조 색상 */
    secondary: string;
    /** 배경색 */
    background: {
      /** 기본 배경 */
      default: string;
      /** 강조 배경 */
      paper: string;
    };
  };
  
  /**
   * 타이포그래피 설정
   */
  typography: {
    fontFamily: string;
    fontSize: {
      small: string;
      medium: string;
      large: string;
    };
  };
}

// 함수 타입
export type OnSubmitHandler = (
  /** 폼 데이터 */
  data: FormData,
  /** 이벤트 객체 */
  event: React.FormEvent
) => void | Promise<void>;

✅ Best Practices

  • ✓ 모든 Props에 JSDoc 추가
  • ✓ 기본값 명시 (@default)
  • ✓ 예제 코드 제공 (@example)
  • ✓ TypeScript로 타입 정의
  • ✓ 컴포넌트 설명 작성
  • ✓ Story별 설명 추가

🎯 문서화 레벨

Level 1: 최소

타입만 정의

Level 2: 기본

+ JSDoc 주석

Level 3: 완전

+ 예제 + 가이드

⚡ 자동화 팁

  • • ESLint로 JSDoc 강제
  • • Prettier로 형식 통일
  • • CI에서 문서 빌드
  • • PR에 문서 링크 추가
  • • 버전별 아카이브

🚀 Pro Tips

문서와 코드 한곳에서

JSDoc 주석은 IDE에서도 표시되어 개발 경험 향상

타입 안정성 + 문서화

TypeScript로 타입 안정성과 자동 문서화 동시 달성

항상 최신 상태

코드 변경 시 문서도 자동 업데이트

팀 협업 강화

디자이너, PM도 쉽게 이해할 수 있는 문서