노트

Storybook

Storybook

프론트엔드#tooling#testing · 연결된 개념 4개

쉽게 말하면

Storybook은 버튼이나 카드 같은 컴포넌트를 앱에서 떼어 쇼룸에 진열해 두고, 기본·비활성·로딩 상태를 하나씩 꺼내 보는 도구예요. 앱 전체를 띄우지 않고도 부품을 확인하고 문서로 남길 수 있죠.

비유의 한계 쇼룸은 구경만 하는 곳이지만 스토리는 play 함수로 클릭 같은 사용자 동작을 실행하는 테스트도 돼요. props만으로 그려지는 presentational 컴포넌트가 가장 진열하기 쉬워요.

Storybook은 UI 컴포넌트를 앱과 떨어진 작업장에서 상태별로 렌더해 보고, 문서화하고, 상호작용을 테스트하는 도구다. 공용 컴포넌트를 모아 디자인 시스템을 만들 때 많이 쓴다.

  • 화면: 왼쪽 사이드바(카테고리 → 컴포넌트 → 스토리), 위쪽 툴바(줌, 배경, 뷰포트, 간격 측정), 아래쪽 애드온 패널(Controls, Actions, Interactions)
  • 스토리: 컴포넌트의 상태 하나를 보여 주는 예시. 버튼의 기본·비활성·로딩이 각각 스토리다

CSF (Component Story Format)

const meta = { component: Button, tags: ['autodocs'],
  argTypes: { onClick: { action: 'clicked' } } } satisfies Meta<typeof Button>
export default meta                                   // 메타데이터 하나
 
export const Primary: StoryObj<typeof meta> = {      // named export 하나 = 스토리 하나
  args: { label: '저장', variant: 'primary' },
  play: async ({ canvas, userEvent }) => {           // 상호작용 시나리오
    await userEvent.click(canvas.getByRole('button'))
  },
}
  • 메타에 title을 주지 않으면 스토리 파일의 경로로 사이드바 위치가 정해진다
  • args: 스토리에 넘길 props. Controls 패널에서 바꿔 볼 수 있다. argTypes로 위젯 종류를 정한다
  • Actions: 이벤트 핸들러 호출을 패널에 기록한다
  • play: 렌더 뒤 사용자 동작을 실행하는 테스트. 문법이 React Testing Library와 같다
  • tags: ['autodocs']로 문서 페이지를 자동 생성하고, parameters.layout으로 배치를 정한다
  • 확장: 접근성 검사(Accessibility, a11y), 시각 회귀(Visual Regression, Chromatic), MSW로 API 모킹 연동

props만으로 그려지는 presentational 컴포넌트가 스토리로 만들기 가장 쉽다.

출처: Storybook - Component Story Format (CSF)

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 컴파운드 컴포넌트 패턴

    컴파운드 컴포넌트(Compound Components)는 여러 컴포넌트가 상태를 공유하며 협력해 하나의 기능을 이루는 패턴이다. HTML(HyperText Markup Language)의 select와 option처럼, 부모가 상태를 들고 자식들은 각자 한 역할만 맡는다.

  • useActionState와 폼 액션

    React 19에서는 <form action={함수}>에 함수를 바로 넘길 수 있고, useActionState가 그 액션의 대기 상태와 마지막 결과를 한 훅으로 관리한다. useState + onSubmit + 로딩 플래그로 짜던 패턴을 대체한다.

  • React로 보는 SOLID

    SOLID는 원래 객체 지향 설계 원칙이지만 React 컴포넌트·props·훅에도 그대로 옮겨 볼 수 있다. 원칙 자체보다 "어떤 코드 모양이 되는가"를 짧게 정리한다.

  • 스텁 큐

    서드파티 SDK 본체가 아직 로드되지 않았을 때, 작은 스텁(stub)이 들어온 호출을 배열에 쌓아 두고 본체가 도착하면 쌓인 호출을 순서대로 처리하는 방식. Google Tag Manager(GTM)의 dataLayer와 gtag.js의 gtag()가 이 구조이고, Meta Pixel의 fbq() 설치 코드도 본체 전 호출을 배열에 쌓는다. 쌓아 두는 배열은 먼저 들어온 것부터 꺼내는 큐로 쓰인다.

  • loading 경계와 레이아웃 끌어올리기

    Next.js App Router에서 loading.tsx는 같은 세그먼트의 page와 그 아래(하위 layout 포함)를 suspense로 감싸지만, **같은 세그먼트의 layout은 감싸지 않는다**. 그래서 데이터를 기다릴 필요가 없는 공통 UI(탭바, 필터 헤더)를 page에서 layout으로 끌어올리면 스켈레톤에 덮이지 않고 처음부터 실제 모습으로 보인다.

보기 옵션