Storybook의 유용함

이걸 도대체 왜 써야한담?

Jisung Park
9 min readFeb 10, 2020

몇 달 전 부서에서 만드는 솔루션에 적용할 UI 구성요소의(그러니까 버튼, 체크박스 등등의) 공통 디자인이 나왔다. 나왔던 타이밍이 좀 애매했기에 내가 참여한 모듈은 어느정도의 구색을 맞추는 수준 정도에서 작업을 끝낼 수 밖에 없었다. 일종의 ‘유예’랄까. 다행히도 ‘유예’에 따라오는 ‘언제 할거냐’라는 지속적인 관심(이라고 쓰고 눈초리라고 읽는 그것)은 이런 저런 사정으로 꽤 긴 기간 방어할 수 있게 되었다.

꽤 긴 유예도 얻었겠다. 당장의 기능개선이나, 화면을 뜯어고쳐야 하는 절체절명의 상황도 아니었던 나는 일단 UI 구성요소 제작부터 천천히 시작했다. 꽤 급했던 개발기간을 단축시키기 위해 도입했던 UI 프레임워크 의존성을 걷어낼 필요도 있었다. (사용했던 UI 프레임워크는 정말 좋았고 도움이 많이 되었지만, ‘튜닝의 끝은 순정’이라는 나의 기조는 크게 달라지지 않았다. 옛날옛적 Vuetify에 너무 많이 데였다.)

아래는 이런 과정에서 Storybook을 도입해 본 후에 얻은 몇가지 깨달음을 정리한 글이다. 이미 Storybook은 세상에 나와 빛을 본지 한참 (요즘같은 세상에 만 4년은 ‘세월’이라고 생각한다) 되었고, 구글링하면 얻을 수 있는 정보들도 많기 때문에 ‘이걸 왜 써야하는지’를 고민할만한 타이밍은 아니지만, 혹시라도 누군가 이게 왜 필요하냐고 나에게 묻는다면 아래 이야기를 해줄 참이다.

Storybook은?

Storybook. 이름 한 번 잘 지었다.

정체가 궁금할 때는 언제나 자기소개부터 찾아보는 법. 자신만만하게 스토리북 홈페이지 메인의 자기소개를 살펴보자

Storybook is an open source tool for developing UI components in isolation for React, Vue, and Angular. It makes building stunning UIs organized and efficient.

… UI를 체계적이고 효율적으로 만들어주는 UI 컴포넌트 개발 오픈소스 툴… 왠지 와닫지 않는 건 나의 영어실력 탓인지 자책하며 Introduction 페이지로 이동해보자.

Storybook is a user interface development environment and playground for UI components. The tool enables developers to create components independently and showcase components interactively in an isolated development environment.
— 스토리북은 UI 개발 환경이자 UI 컴포넌트를 위한 놀이터입니다. 개발자들이 컴포넌트를 독립적으로 만들고, 격리된 개발 환경에서 상호작용이 가능한 컴포넌트를 선보일 수 있도록 해줍니다

이거다. 나의 부족한 영어실력으로도 이해할 수 있는 깔끔한 소개다.

더 말할 나위 없는 깔끔한 소개. Storybook의 유용함은 이 문장에 모두 담겨있다고 생각한다. 그럼 무엇이 어떻게 유용한 지 하나씩 살펴보자.

나한테는 — UI 컴포넌트를 위한 놀이터

React로 공통 UI 컴포넌트를 작성해야하는 중책을 맡았다고 생각해보자. 시작은 버튼. 버튼 컴포넌트 소스파일을 하나 만들고, 프로퍼티를 정의하고, 스타일을 작성하고, JSX 태그와 함께 원하는 소스를 작성한다. 이제 제대로 뜨는지 확인해보기 위해 테스트용 빈 페이지 하나를 만들고, 테스트 페이지에 버튼을 import해서 dev-server를 돌리면… 뜬다! 다행히 아주 잘 뜬다.

끝이냐고? 이제 시작이다. disabled 됐을 때 동작을 테스트해야되니까 테스트 페이지에 띄워놓은 버튼 프로퍼티에 disabled를 추가해본다. 오케이, 이것도 되고. 크기랑 색깔 variant도 정의해놓은 게 있는데 다시 한 번 수정. 아, 그럼 다 같이 비교해볼까? 버튼 추가, 추가… 자 이제 버튼은 됐고 Input이다. Input 만들고, 테스트 페이지에 띄우고, 프로퍼티도 수정해보고 등등등… 어우 테스트 페이지가 너무 지저분한데? 한번 싹 지우고… 그 다음은 Checkbox. 어, 근데 버튼 다시 봐야할것 같은데? 그럼 다시 버튼 import…

이러다보면 수업시간에 졸면서 쓴 연습장같은 테스트페이지를 작성했다 지웠다를 귀찮게 반복하고 있는 나를 발견하게 된다. 그런데 그게 테스트페이지가 아니라 실제 개발하려던 페이지였다면? 다시 원상복구… 하기도 전에 커밋해버렸다. 이런 제길…

Storybook은 놀이터, 혹은 잘 정돈된 연습장이다. 컴포넌트별로, 혹은 케이스별로 한 페이지씩 쉽게 써서 던져놓자. 다른 연습장에 코드를 작성하다가도 생각나면 이전에 썼던 페이지도 쉽게 들여다보고. 실제 소스에 영향을 주지도 않는다. 더 귀찮은 거 아니냐고? 생각보다 쉽다. 5.2 버전에서 CSF 문법이 생기면서 훨씬 간단해졌다.

Storybook으로 작성한 연습장. default export를 제외하고 export 한줄 당 연습장 한장이다.

개발자들끼리는 — 생각보다 꼼꼼한 매뉴얼

위에서 잘 만든 공통 컴포넌트를 공유하고, 사용할 때 Storybook은 다시 한번 빛을 발한다. 어디선가 누군가 ‘가장 좋은 소스는 주석이 필요 없는 소스’라고는 하지만, 그 컴포넌트에 어떤 프로퍼티들이 있는지, 어떤 프로퍼티에 어떤 값을 입력할 수 있는지, 어떤 값을 입력했을 때 어떻게 변하고 동작하는지를 온전히 소스만 보며 익히는 것은 쉬운 일이 아니다. 이럴 때 유즈케이스별로 잘 분류된 연습장, 그러니까 용례들이 소스와 함께 제공된다면 함께 개발하는 입장에서는 도움이 많이 될 수 있다.

Storybook의 공식 애드온들도 많은 도움이 된다. storysource를 이용하면 해당 story를 구현하기 위해 어떤 프로퍼티를 입력했는지를 볼 수 있고, actions로 onChange 같은 handler들이 어떤 값을 넘겨주는지도 확인할 수 있다. 그리고 그 정점은 Docs. 해당 컴포넌트의 API 문서를 간편하고 깔끔하게 만들어낼 수 있다. React의 경우 react-docgen 등의 도움을 받으면 컴포넌트 소스로 문서를 자동으로 생성할 수도 있다. 필요하다면 MDX를 이용하는 것도 가능하다.

소스만 짜시면 문서는 추가구성으로 드립니다. docgen의 마크다운 문법 지원은 덤!

디자이너와는 — 커뮤니케이션 도구

절정의 디자인 감각을 자랑하는 속칭 ‘디발자’가 아니라면, 보통 우리는 UX(혹은 CX) 디자이너들과 협업을 하게 되는데, 개중에는 정적인 디자인만 주고 동적인 움직임에 대한 지침을 주지 않는 경우도 있다. 예를 들면, 버튼을 클릭해서 띄우는 팝업이 있을 때 ‘이 팝업은 바깥 영역 클릭을 허용하는지/아닌지’ 나, 팝업을 닫을 때 ‘버튼으로 토글 해서 닫는 것인지/팝업 바깥 영역을 클릭해서 닫는 것인지’ 등은 zeplin 등으로 주는 정적 디자인으로는 다 알기 어렵다.

이때부터 디자이너와 개발자의 끝없는 메신저 혹은 메일의 핑퐁이 이루어진다. (같은 장소에서 이야기한다면 참 좋으련만!) 하지만 글은 언제나 보는 것보다 길게 마련이고, 구구절절한 텍스트는 종종 착오를 가져오게 마련이다. (가끔은 서로 다른 세계에 사는 것 같이 느껴질 때도 있다)

백문이 불여일견, Storybook이 우리의 훌륭한 대화 도구가 되어 줄 것이다. 멀리 떨어진 디자이너랑 대화하려고 웹서버까지 띄워놓는 수고가 어렵다면, 그냥 정적 페이지로 Storybook을 빌드 해주어도 된다. 물론 거리의 장벽을 완벽히 메울 수는 없고, 메신저와 메일의 핑퐁은 여전하겠지만 그래도 대화의 공통 매개체가 존재한다면 서로가 설명해주기 더 쉽지 않을까.

기타등등 — 가보지 못한 길

간단히 사용해 보고 얻은 결론은 이 정도인데, 아직까지 시도해보지 못한 것이 많아 어떤 장점이 더 있을지, 혹은 명백한 한계가 어디까지일지 확신할 수는 없다. 첫 릴리즈 이후 꽤 오랜 시간이 지났지만 문법이나 설정 방법도 계속 새롭게 등장하거나 바뀌고, 꽤 뜬금없는 부분에서 지뢰를 밟아 고생하는 일을 겪어서 Storybook이 만능키라고 말할 수 없기도 하다. (자세한 것은 후술) 다만 혹시 위와 비슷한 어려움을 겪는다면 ‘한 번쯤 직접 시도해볼 만한 대안’ 임에는 틀림이 없다.

사족: Storybook 좌충우돌기

  • 5.2 버전까지는 Typescript+React로 작성한 소스를 제대로 파싱 하지 못하거나, 주석의 마크다운 문법이 지원되지 않거나, ts 에러를 뿜어내는 경우들이 있었다. 다행히 5.3 버전에서는 해결되어서 좀 더 쉽게 사용할 수 있다.
  • v5 버전에서 새로운 설정법이 도입되었는데, 이전에는 홈페이지 Docs에도 제대로 반영되어 있지 않은 경우도 있었고, 구글링해서 얻을 수 있는 자료에도 대부분 이전 버전의 설정법들이 나와있다. 혹시 두 설정법을 섞어 쓰지 않도록 하자. (v5에서는 main.js가 중심이 되며, addons/presets 등의 파일을 하나로 통합한 형태로 설정이 가능하다)
  • 만약 프로젝트에서 babel을 쓰지 않는다고 해도 storybook을 실행하기 위해서는 @babel/core와 babel-loader를 설치해야 할 수도 있다.
  • 스토리북은 내장된 별도의 webpack 설정이 존재하는데, 이때 그림파일 등의 loader로 기본 설정되어 있는 file-loader는 현재 릴리즈를 기준으로 4.0 버전대를 사용하고 있다. 만약 프로젝트에서 5.0버전의 file-loader를 사용하고 있고, dev-server에서는 그림이 불러와지는데 storybook에서는 불러와지지 않는다면, file-loader의 차이에서 오는 import 문법의 차이를 확인해보자. 5.0 버전의 file-loader를 사용하고 싶다면 storybook의 webpack 설정을 바꿔주어야 한다. (현재 알파 릴리즈 단계인 6.0에서는 file-loader 5.0 버전이 dependency로 설정되어 있다.)
  • 아직 @yarn/berry에서 기본이 된 PnP를 지원하지 않는다. ㅠㅠ (우회로가 있지만… 너무 힘들다) 이것도 아마 6.0버전에서 정식으로 지원될 것 같다.

--

--