버튼 하나 고치려고 로그인부터 다시 해야 하나요? (Storybook의 필요성)
1. "그 모달 수정했어? 확인 좀 하게 띄워봐."
결제 실패 모달(PaymentErrorModal)의 디자인을 수정해야 했습니다.
그런데 이 모달을 보려면...
- 로그인을 한다.
- 상품을 장바구니에 담는다.
- 결제 페이지로 간다.
- 카드 정보를 일부러 틀리게 입력한다.
- 결제 버튼을 누른다.
- (로딩 대기) -> 짠! 모달 등장.
CSS 한 줄 고치고 저장할 때마다 이 짓을 반복해야 했습니다. "아, 그냥 모달만 따로 떼서 보고 싶다!"
2. 처음엔 뭐가 이해가 안 갔나? (문서화 도구인 줄 알았다)
저는 Storybook이 "디자이너를 위한 예쁜 문서 만드는 도구"인 줄 알았습니다. "우린 스타트업이라 문서 관리할 시간 없어. 바빠 죽겠는데 무슨 스토리북이야."
하지만 Storybook의 진가는 문서화가 아니라 "개발 속도 향상(Development Velocity)"에 있습니다. 앱 전체를 실행하지 않고, 컴포넌트 하나만 똑 떼어내서(Isolation) 독립적으로 개발할 수 있게 해주는 "컴포넌트 실험실"입니다.
3. 어떤 포인트에서 이해가 됐나? (부품 공장 비유)
이걸 "자동차 조립"에 비유하니 이해가 됐습니다.
- 기존 개발: 엔진 수리하는데 자동차에 직접 타서 시동 걸고 주행 테스트까지 함. (비효율)
- Storybook: 엔진만 작업대에 올려놓고 전선 연결해서 돌려봄. (효율)
PaymentErrorModal을 스토리북에 등록하면, 브라우저 켜자마자 모달이 떠 있습니다.
로그인도, 결제 시도도 필요 없습니다.
그냥 CSS 고치면 0.1초 만에 반영됩니다.
4. 해결 과정: CDD (Component Driven Development)
1단계 - 스토리 만들기
Button.tsx 옆에 Button.stories.tsx를 만듭니다.
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
title: 'Common/Button',
};
export default meta;
type Story = StoryObj<typeof Button>;
// 기본 상태
export const Default: Story = {
args: {
label: 'Click Me',
variant: 'primary',
},
};
// 에러 상태 (이거 보려고 로그인 안 해도 됨!)
export const Error: Story = {
args: {
label: 'Error',
variant: 'danger',
},
};
2단계 - Controls로 가지고 놀기
스토리북 UI에서 variant를 드롭다운으로 바꾸거나, label 텍스트를 실시간으로 수정할 수 있습니다.
디자이너한테 "이거 폰트 크기 16px로 하면 어때요?"라고 물어볼 필요 없이,
스토리북 링크 던져주고 "직접 조절해 보세요"라고 하면 됩니다. 커뮤니케이션 비용이 0이 됩니다.
3단계 - 엣지 케이스 테스트
"이름이 100글자면 버튼이 깨지나요?"
실제 앱에서는 이름 100글자 넣어서 가입하기 힘들지만,
스토리북에서는 args에 100글자 붙여넣으면 1초 만에 확인 가능합니다.
export const LongText: Story = {
args: {
label: 'Super Long Text Super Long Text Super Long Text...',
},
};
5. 깊이 파고들기 - Mocking (가짜 데이터 주입)
"API 호출하는 컴포넌트는요?"
msw-storybook-addon을 쓰면 네트워킹도 가로채서(Mocking) 가짜 응답을 줄 수 있습니다.
// UserProfile.stories.tsx
export const Success: Story = {
parameters: {
msw: {
handlers: [
http.get('/api/user', () => {
return HttpResponse.json({ name: 'Batman' });
}),
],
},
},
};
이제 백엔드 서버가 죽어있어도 프론트엔드 개발은 멈추지 않습니다.
6. Interaction Testing (클릭 자동화) 더 알아보기
Storybook은 단순히 "보여주는" 것을 넘어 "동작"을 테스트할 수 있습니다.
play 함수를 사용하면, 사용자의 클릭/입력을 시뮬레이션할 수 있습니다. (Jest + Testing Library 내장)
import { userEvent, within } from '@storybook/testing-library';
export const SubmitForm: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
// 1. 이메일 입력
await userEvent.type(canvas.getByLabelText('Email'), 'test@example.com');
// 2. 비밀번호 입력
await userEvent.type(canvas.getByLabelText('Password'), '1234');
// 3. 로그인 버튼 클릭
await userEvent.click(canvas.getByRole('button'));
// 4. 성공 메시지 확인
await expect(canvas.getByText('Welcome!')).toBeInTheDocument();
},
};
이렇게 하면 스토리북을 킬 때마다 자동으로 폼을 채우고 제출하는 시나리오가 실행됩니다. QA 팀에게 넘기기 전에 개발자가 스스로 기능 검증을 끝낼 수 있습니다.
7. Accessibility Testing (접근성 자동화) 파헤치기
storybook-addon-a11y를 설치하면, 내 컴포넌트가 웹 접근성 표준(WCAG)을 지키는지 자동으로 검사해줍니다.
- "버튼 명암비가 너무 낮아서 안 보임"
- "이미지에 alt 태그 빠짐"
이런 실수를 배포 전에 잡아낼 수 있습니다. 접근성은 나중에 고치려면 지옥이지만, 처음부터 챙기면 습관이 됩니다.
8. Pro Tip: Figma 연동
디자이너가 Figma에서 작업한 디자인을 Storybook 패널 옆에 띄울 수 있습니다.
storybook-addon-designs를 쓰면 됩니다.
개발자는 코드를 짜면서, 바로 옆 탭에서 "디자인 시안"을 픽셀 단위로 비교할 수 있습니다. "디자인이랑 다른데요?"라는 말을 들을 확률이 현저히 줄어듭니다.
9. 요약
- Storybook은 문서 도구가 아니라 '개발 부스터'다. 로그인 과정 없이 UI를 바로 수정할 수 있다.
- 엣지 케이스(긴 텍스트, 에러 상태)를 1초 만에 재현한다.
- MSW로 백엔드 없이 개발하고, Play 함수로 클릭 테스트까지 자동화한다.
- 컴포넌트를 격리해서 개발하면 속도가 10배 빨라진다.