OHTAEJUN
OHTAEJUN
Taejun0-portfolio
HomeAboutProjectsBlog
목록으로

Why? StoryBook

2026-05-27 · Design, stack, 프론트엔드

서론

기술적 의사결정 시리즈의 첫 번째 글로 내가 왜 Storybook을 사용하게 되었는지 그 근거를, 나아가 해당 기술의 동작원리도 함께 분석하고자 한다.

특히, 해당 글에서는 기존에 생각했던 의사결정 과정을 넘어서 스토리북이라는 스킬이 어떻게 동작하는지 그에 대한 분석도 진행하고자 한다.

프로젝트에서 Storybook을 사용하게 된 계기

처음 Storybook을 쓴 이유는 굉장히 단순했다. 디자인 시스템을 빠르게 구성하고 나와야하는 프로젝트에서 디자인 시스템만 따로 디자이너에게 공유하기 좋은 형태라고 생각했기 때문이다.

Storybook에서 제공하는 공식 문서는 나의 생각을 뒷받침 해주었다.

반응형 이후 UI는 하나가 아니라 수많은 상태를 가지게 됐고, React 같은 도구로 컴포넌트를 잘게 나눠도 그 상태가 앱·API·라우팅에 묶여 있어서 쉬이 꺼내보기 어렵다는 점이다.

그래서 Storybook 제시하는 해법은 두 개다. 앱 없이 컴포넌트만 그리고, 그 상태를 story라는 장면으로 남긴다.

당시, 나는 Story 라는 가장 최소 단위의 UI를 쌓아가는 형태로 Design System을 구성하기로 하였고 주요 도구로써 채택하게 되었다.

본론

서론에서 말했듯 내가 Storybook을 사용하게 된 계기는 "디자인 시스템"과 그걸 디자이너에게 넘겨줄 수 있는 결과물이었다. 그 근거를 "공식 문서"에서 찾았었는데, 이제는 Storybook 자체에 대해 분석해보고자 한다.

Storybook 이란?

한 줄로 말하면, Storybook은 앱 없이 돌아가는 프론트엔드 작업장이다.

공식 표현도 같다. frontend workshop for building UI components and pages in isolation. 개발, 테스트, 문서화가 한 도구 안에 붙는 이유이기도 하다.

이름을 그대로 읽으면 이해가 빠르다. story는 컴포넌트의 특정 상태를 잡아 둔 장면이고, book은 그 장면들을 넘기며 보는 목록이다. 애자일의 User Story와는 결이 다르다. Button이라는 부품이 단위가 아니라, 그 버튼의 Default, Loading, Disabled, Error가 각각 하나의 이야기, 즉 story다.

Storybook의 해결 과제 및 방법

현대 프론트엔드는 페이지 하나가 아니라 UI의 수많은 변화 상태를 담아낸다.

반응형 웹이 화면을 하나에서 열, 백, 천 개로 쪼갰고, 그 위에 기기·브라우저·접근성·성능·비동기 상태가 겹친다. React, Vue, Angular는 복잡한 UI를 컴포넌트로 나누게 도와주지만, 은탄환은 없다. 프로젝트가 커지면 컴포넌트 수가 늘고, 각 컴포넌트는 다시 수천 개의 서로 다른 변주를 만든다. 더 골치 아픈 지점은 그 UI가 비즈니스 로직, 인터랙티브 상태, 앱 맥락에 얽혀 있어서 디버깅하기 어렵다는 것이다.

결제가 끝난 뒤에만 뜨는 모달을 보려면, 변수를 조작하거나 실제로 결제를 다시 해야 할 수도 있다. 원하는 화면을 꺼내보는 비용이 너무 크다.

Storybook의 2가지로 이를 해결하고자 하였다.

첫 번째는 isolation이다. 컴포넌트는 앱 전체를 띄우지 않아도 렌더할 수 있다. props를 넣고, 데이터를 mock하고, 이벤트를 흉내 낸다. Storybook은 앱 옆에 붙는 작은 개발 전용 공간이고, 비즈니스 로직이 개입하지 않는 iframe 안에서 그린다.

두 번째는 그 모든 것을 story로 저장하는 것이다. story는 props와 mock을 선언적으로 적어, “이 입력이면 이렇게 보여야 한다”를 고정한 파일이다. 한 컴포넌트에 story는 여러 개일 수 있다. 한 번 적어 두면 개발, 테스트, 문서에 같은 장면을 재사용한다.

최소 단위가 컴포넌트가 아니라 장면인 이유가 여기 있다. 디자인 시스템을 Button.tsx 파일 목록으로 쌓으면, 그 버튼이 로딩 중일 때 어떻게 보이는지는 앱 안에 숨어 버린다. Loading이라는 story가 있으면, 그 상태는 목록에서 바로 펼칠 수 있는 항목이 된다. 당시 내가 “story를 쌓아 디자인 시스템을 구성한다”고 한 말은, 사실 상태에 다한 목록을 만든다는 쪽에 가깝다.

Storybook의 동작 원리

Storybook은 앱과는 별도의 node를 통해서 미리보기 "서버"를 새로 띄우는 방식으로 동작한다.

동작 구조

Storybook은 보통 프로덕션 번들에 들어가지 않는다. 앱을 설치하듯 devDependency로 얹고, 개발할 때만 별도 명령으로 켠다. Next.js 앱이 pnpm dev로 뜨는 것과 별개로, pnpm storybook이 또 하나의 노드 프로세스를 띄운다. UI만 볼 때는 앱 서버 없이 Storybook만 켜도 된다.

떠 있는 화면은 사실 두개의 층을 가진다.

  • Manager: 왼쪽 사이드바. 컴포넌트와 story 목록, 검색, addon 패널.
  • Preview: 가운데 iframe. 선택한 story만 렌더한다. 앱 라우팅, 로그인, API가 기본으로 붙어 있지 않다.

이때 iframe을 사용하는 이유는 storybook 화면 자체의 css도 존재하기 때문이다. 예를 들어 storybook에서 사용하는 ui와 실제 사용자가 만든 ui의 css가 겹치게 된다면 충돌이 일어날 수 있기 때문에 명확한 공간을 분리한다.

story 파일은 특별한 바이너리가 아니다. JavaScript/TypeScript 모듈이고, 공식 포맷은 Component Story Format(CSF) 이다. 각 story는 함수로 export되므로 Jest, Vitest, Testing Library, Chromatic 같은 도구에 그대로 넘길 수 있다. 문서에서는 write stories once, reuse everywhere라고 칭한다.

특히 storybook의 Preview는 실제 앱 전체를 실행하는 게 아니기에 앱에서 원래 상위에 선언해온 Provider들이 자동으로 따라오지 않는다. Context Provider가 필요한 컴포넌트는 decorator로 감싸서 필요한 context를 제공해야한다.

장점

  1. 컴포넌트를 독립적으로 개발할 수 있다. 실제 서비스 전체를 실행하지 않고 Button, Modal, Card 같은 특정 컴포넌트만 Storybook에서 바로 렌더링할 수 있다. 예를 들어 결제 완료 모달을 확인하기 위해 실제로 로그인부터 결제까지 진행할 필요 없이 Success Story를 선택해서 바로 확인할 수 있다.
  2. 다양한 UI 상태를 쉽게 재현할 수 있다. 실제 서비스에서는 Loading, Error, Empty, Disabled 같은 상태를 만들기 위해 API 응답이나 특정 사용자 행동이 필요할 수 있다. Storybook에서는 args를 이용해 원하는 props를 직접 넘길 수 있기 때문에 이러한 상태를 독립적으로 만들어 확인하기 쉽다.
  3. 컴포넌트 자체가 하나의 문서가 된다. Storybook을 보면 어떤 컴포넌트가 존재하고 어떤 props를 받으며, 각각의 상태에서 어떻게 보이는지 확인할 수 있다. 따라서 별도의 UI 문서가 없더라도 Story를 통해 컴포넌트의 사용 방법과 상태를 어느 정도 공유할 수 있다.
  4. 디자인 시스템을 관리하기 좋다. Button, Input, Modal처럼 여러 화면에서 공통으로 사용하는 컴포넌트를 Storybook에 모아두면 일관된 UI를 관리하기 쉬워진다. 개발자뿐만 아니라 디자이너나 QA도 실제 페이지에 들어가지 않고 컴포넌트의 모습을 확인할 수 있다는 장점이 있다.
  5. 테스트로 확장하기 좋다. Story는 단순한 예시 화면이 아니라 특정 컴포넌트 상태를 재현하는 데이터가 된다. 따라서 만들어둔 Story를 이용해 사용자 interaction 테스트나 접근성 검사, Chromatic 같은 시각적 회귀 테스트로 확장할 수 있다.

단점

  1. Story 자체를 별도로 관리해야 한다. 컴포넌트를 만들면 끝나는 것이 아니라 해당 컴포넌트의 Story도 작성해야 한다. 이후 props나 UI 구조가 변경됐는데 Story를 같이 수정하지 않으면 실제 컴포넌트와 Storybook의 내용이 달라질 수 있기 때문에 지속적인 관리 비용이 생긴다.
  2. 실제 애플리케이션의 환경이 자동으로 따라오지 않는다. Storybook은 컴포넌트를 실제 앱과 분리해서 실행하기 때문에 ThemeProvider, Router, Redux, React Query 같은 환경이 기본적으로 존재하지 않는다. 이런 의존성이 필요한 컴포넌트는 Decorator를 이용해 Provider를 감싸거나 별도의 설정을 추가해야 한다.
  3. API나 인증에 의존하는 컴포넌트는 Mocking이 필요하다. Storybook에는 실제 앱의 로그인 상태나 백엔드 API가 자동으로 연결되는 것이 아니다. 서버 데이터를 사용하는 컴포넌트를 독립적으로 보여주려면 MSW 등을 이용해 API 응답을 Mocking해야 하기 때문에 복잡한 컴포넌트일수록 초기 설정이 많아질 수 있다.
  4. Storybook에서 정상이라고 실제 서비스까지 정상인 것은 아니다. Storybook은 어디까지나 격리된 환경에서 컴포넌트를 확인하는 도구다. 실제 서비스에서는 부모 레이아웃, 다른 컴포넌트, 실제 API, 라우팅, 전역 상태 등이 함께 동작하기 때문에 Storybook에서 통과했다고 전체 서비스의 정상 동작까지 보장되는 것은 아니다.
  5. 프로젝트 규모에 따라 관리 대상이 크게 늘어날 수 있다. 컴포넌트 하나에도 Default, Loading, Error, Disabled, Mobile 등 여러 Story가 생길 수 있다. 따라서 모든 상태를 무작정 Story로 만들기보다는 실제로 확인하거나 공유할 가치가 있는 상태를 기준으로 관리하는 것이 중요하다. 정리

기대 효과

공식문서에 따르면 Storybook을 UI의 single source of truth라고 부르고, story는 시안이 아니라 실제로 동작하는 UI를 보여 준다고 한다. 정적 사이트로 배포하면 개발자·디자이너·PM이 로컬 환경 없이 같은 URL을 본다. Figma에는 그림을 붙이는 게 아니라, 돌아가는 컴포넌트를 embed할 수 있다. Autodocs는 그 장면들로부터 사용 가이드를 자동으로 만든다.

다만 실제로 체감이 컸던 효과는, 공유 자체보다 공유하려면 컴포넌트가 떨어져 나와야 한다는 압박이었다. 카카오엔터테인먼트 글에서도 동일한 언급을 한다. 독립 환경에서 다시 그리려면 의존성이 낮아야 하고, 재사용이 쉬워야 한다. 스토리로 안 옮겨지면 한 컴포넌트가 너무 많은 일을 하거나, 부모 스타일·전역 훅에 기대고 있을 가능성이 크다.

결론

나는 Storybook을 디자인 시스템을 쌓고, 디자이너에게 넘겨줄 형태로 선택했다. 근거는 공식 문서였고, 그때는 그 문장을 거의 그대로 가져왔다.

다시 분석해보면서 storybook의 핵심은 격리와 story임을 알았다. 앱 없이 한 상태를 장면으로 남길 수 있어야, 그 목록이 디자인 시스템이 되고, 배포와 Figma 공유가 따라온다.

storybook은 초기 세팅이나, 개발 속도 면에서 약간 불리한 특성을 가질 수는 있지만, 추후 있을 개발 환경을 위해서 장기적으로는 큰 도움이 되는 도구였다.

Comments

댓글은 아직 연결해 두지 않았습니다. 곧 열어둘 예정이에요.

HomeAboutProjectsBlog
xownswns@naver.com
GHVL

taejun0

© 2026 오태준