Storybook으로 컴포넌트 문서화와 시각 회귀 테스트

스토리로 문서화하고 시각 회귀를 자동으로 잡는 방법

Storybook 시각 회귀 테스트 썸네일

핵심 요약

  1. 스토리는 프롭 조합 전부가 아니라 기본·변형·예외 상태를 대표하도록 설계한다.
  2. 상호작용 스토리는 컴포넌트 수준 통합 테스트로 재사용되고, 역할 기반 쿼리를 E2E와 공유한다.
  3. 시각 회귀는 의미 있는 컴포넌트에 좁혀 적용하고 애니메이션·시간 의존 값은 고정한다.
  4. 컴포넌트 추가와 문서 갱신을 같은 PR에서 처리해 문서가 뒤처지지 않게 한다.

컴포넌트가 늘어나면 "이 버튼은 어떤 상태까지 있는가", "비활성일 때 색은 무엇인가"를 매번 코드를 열어 확인하게 된다. 디자인 시스템을 표방하면서도 실제 사용 규칙이 사람 머릿속에만 있으면, 신규 팀원은 기존 화면을 복사하는 방식으로 배운다. Storybook은 컴포넌트를 상태별로 렌더링해 문서로 만들고, 그 스토리를 시각 회귀 테스트의 기반으로 재사용할 수 있게 한다. 이 글은 스토리 설계부터 자동화까지의 흐름을 정리한다.

컴포넌트 문서화가 필요한 시점

다음 신호가 보이면 문서화를 시작할 때다.

  • 같은 컴포넌트를 화면마다 다르게 쓰고 있어 variant가 갈라진다.
  • 디자인 변경 후 어느 화면이 영향을 받는지 알기 어렵다.
  • 신규 입사자가 기존 화면을 복사해 컴포넌트를 재구현한다.
  • 스타일 수정이 예상치 못한 화면을 깨뜨린다.

스토리 설계와 상태 커버리지

스토리는 "그 컴포넌트가 가질 수 있는 상태"를 대표해야 한다. 프롭 조합을 전부 나열하는 것이 아니라, 의미 있는 상태를 고른다.

// Button.stories.ts
export const Primary = { args: { variant: "primary", children: "저장" } };
export const Disabled = { args: { variant: "primary", disabled: true, children: "저장" } };
export const Loading = { args: { variant: "primary", loading: true, children: "저장" } };

기본·변형·에러 상태 스토리 나누기

상태를 세 층으로 나누면 빠뜨리기 어렵다. 기본 상태, 시각적 변형(크기·색·밀도), 예외 상태(로딩·에러·빈 값·긴 텍스트)다. 특히 긴 텍스트와 좁은 화면은 실제 서비스에서 자주 깨지는 지점이라 스토리로 남겨 두면 회귀를 조기에 잡는다.

상호작용 테스트 붙이기

스토리는 정적 렌더링에 그치지 않는다. Storybook 공식 상호작용 테스트 문서에 따르면 play 함수와 canvasElement, userEvent, getByRole 쿼리를 조합해 사용자 상호작용을 스토리에 붙이면 그 자체가 컴포넌트 수준의 통합 테스트가 된다. 열기·닫기, 입력, 키보드 이동 같은 동작을 스토리와 함께 관리하면 문서와 테스트가 같은 출처를 공유한다.

export const OpensOnClick = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    await userEvent.click(canvas.getByRole("button", { name: "메뉴" }));
    await expect(canvas.getByRole("menu")).toBeVisible();
  }
};

여기서 쓰는 역할 기반 쿼리는 E2E 테스트와도 일관된다. 컴포넌트 단위에서 빈 경로와 상태 전이를 검증하는 기준은 AI 생성 코드에 테스트 붙이기의 커버리지·경계값 점검 흐름과 함께 보면 설계하기 쉽다.

시각 회귀 테스트 연동

스토리가 상태를 대표하면, 렌더링 결과를 이미지로 저장해 이전과 비교함으로써 의도치 않은 시각 변화를 잡을 수 있다. 기준 이미지와 현재 이미지를 비교해 차이가 나면 검토를 요청한다. 도구에 따라 클라우드 서비스로 스냅샷을 관리하거나, 직접 스크린샷을 찍어 비교할 수 있다.

방식장점주의점
전용 시각 회귀 서비스기준 이미지 관리·리뷰 UI비용·스토리 수에 따른 실행 시간
스크린샷 스크립트도구 종속 적음비교·기준 관리 직접 구현

폰트 렌더링, 애니메이션, 시간 의존 콘텐츠는 시각 회귀로 잡으면 안 되는 노이즈의 대표 사례다. 애니메이션은 특정 시점에서 정지시키고, 시간·난수에 의존하는 값은 스토리에서 고정한다.

문서 사이트 배포와 접근 권한

스토리북은 정적 사이트로 빌드해 사내에 배포할 수 있다. 배포 위치는 CI에서 빌드 결과를 올리는 방식이 일반적이며, 접근 권한을 제한해 미완성 컴포넌트가 외부에 노출되지 않도록 한다. 스토리북 문서 자체가 "현재 사내 컴포넌트 카탈로그" 역할을 하므로, 컴포넌트 추가와 문서 갱신을 같은 PR에서 처리하는 규칙을 두면 문서가 뒤처지지 않는다.

접근성 검사와 문서 신뢰도

스토리는 시각 회귀만을 위한 것이 아니다. 각 스토리를 렌더링하면서 접근성 검사를 함께 돌리면 역할·레이블·대비 같은 문제를 컴포넌트 단계에서 잡는다. 문서에 "이 컴포넌트는 키보드로 조작 가능하다"고 적어 두려면 그 주장을 스토리 테스트가 뒷받침해야 한다. 문서와 실제 동작이 어긋나면 아무도 문서를 신뢰하지 않게 되고, 결국 다시 코드를 읽게 된다. 접근성 검사로 자동 판별되는 범위는 제한적이므로, 자동 검사로 걸러낸 뒤 키보드 이동과 스크린리더 확인을 수동 체크리스트에 남긴다.

스토리 이름과 문서 문구는 컴포넌트를 처음 보는 사람의 질문에 답하도록 쓴다. "언제 쓰는가", "무엇을 피해야 하는가"를 한 줄로 덧붙이면 카탈로그가 사용 설명서 역할을 한다.

유지보수 비용을 낮추는 규칙

스토리가 많아지면 실행 시간과 관리 부담이 커진다. 다음 규칙이 비용을 낮춘다.

  • 의미 있는 상태만 남기고 중복 스토리를 합친다.
  • 시각 회귀는 변경 영향이 큰 공통 컴포넌트 위주로 좁힌다.
  • 공통 설정(테마·데코레이터)을 한곳에 모아 스토리마다 반복하지 않는다.

결국 스토리는 문서이자 테스트다. 컴포넌트를 소유하고 관리하는 규칙과 함께 두어야 오래 유지된다. 스토리 렌더링 단계에서 자동 접근성 검사와 수동 키보드 확인을 나누는 기준은 WCAG 2.2 기준 접근성 점검 가이드에서 더 자세히 다룬다.

초보자가 자주 실수하는 포인트

  • 모든 프롭 조합을 스토리로 만들어 실행 시간과 관리 부담을 키운다.
  • 애니메이션·시간 의존 콘텐츠를 그대로 두어 시각 회귀가 상시 실패한다.
  • 스토리를 별도 저장소에 두어 컴포넌트 변경과 문서가 따로 논다.

체크리스트

  • 컴포넌트별 기본·변형·예외 상태를 스토리로 정의했다.
  • 상호작용이 있는 컴포넌트에 play 함수 기반 테스트를 붙였다.
  • 시각 회귀 대상을 영향이 큰 공통 컴포넌트로 좁혔다.
  • 애니메이션·시간·난수 의존 값을 스토리에서 고정했다.
  • 스토리북을 정적 배포하고 접근 권한과 갱신 규칙을 정했다.

자주 묻는 질문

Storybook과 시각 회귀 도구는 꼭 같이 써야 하나요?

필수는 아니다. 스토리만으로 문서화 효과가 크다. 시각 회귀는 공통 컴포넌트가 많아 수동 확인이 어려울 때 자동화 이득이 커진다.

스토리를 얼마나 잘게 나눠야 하나요?

의미 있는 상태 단위로 나눈다. 시각적으로나 동작상 다른 상태만 스토리로 남기고, 단순 프롭 조합은 args로 표현한다.

문서 사이트는 어떻게 배포하나요?

정적 빌드 결과를 CI에서 사내 호스팅에 올리는 방식이 일반적이다. 접근 권한을 제한해 미완성 컴포넌트 노출을 막는다.

참고 자료 · 검증 기준

위 자료와 내용을 대조한 날짜: . 도구·서비스 정책은 이후 바뀔 수 있으므로 적용 전 공식 문서를 다시 확인하세요.

이 글은 실제 실무 환경 테스트 및 검증된 기술 자료를 바탕으로 작성되었으며, 환경 변화에 따라 지속적으로 갱신됩니다.