CRA로 만든 프로젝트에 Storybook 적용 / 유용한 팁 / 강의를 마치면서..

Minjun Kim·2019년 11월 24일
26

6. CRA로 만든 프로젝트에 storybook 적용

우리가 디자인 시스템을 만들때만 스토리북을 사용 할 수 있는건 아닙니다. 꼭 디자인 시스템이 아니여도, 기존에 존재하던 웹 프런트엔드 프로젝트에 스토리북을 적용하면 컴포넌트 문서화를 할 때 편하므로 매우 유용합니다.

디자인 시스템을 만들기 위하여 프로젝트를 아예 분리하는것이 번거로운 상황이라면, 기존 프로젝트에 바로 적용하는것도 나쁘지 않은 선택입니다. 추가적으로, 디자인 시스템에 해당하지 않는 컴포넌트들도 문서화를 제대로 하고자 한다면 Storybook을 적용하면 좋겠지요?

방법은 매우 간단합니다. CRA 로 만든 프로젝트 디렉터리에서 다음 명령어를 실행하시면 됩니다. (새로운 프로젝트를 만드시거나, 5-2 에서 만들었던 sampleapp 프로젝트에서 바로 작업을 진행하시면 됩니다.)

npx -p @storybook/cli sb init

만약 여러분의 프로젝트가 CRA로 만든 프로젝트가 아니라면? 이 링크를 읽어주세요. 직접 설정하는것도 그렇게 번거롭지는 않습니다.

그러면, 프로젝트에 .storybook 디렉터리가 생성됩니다. 생성된 config.js 를 열어보시면 다음과 같은 코드가 있습니다.

src/config.js

import { configure } from '@storybook/react';

// automatically import all files ending in *.stories.js
configure(require.context('../src/stories', true, /\.stories\.js$/), module);

이 설정에서는 스토리 파일을 src/stories 경로에서만 읽고 js 확장자만 처리하고있습니다. 우리는 TypeScript를 사용 할 것이므로, 확장자도 바꿔주고 경로도 '../src'로 바꿔주세요.

src/config.js

import { configure } from '@storybook/react';

// automatically import all files ending in *.stories.js
configure(require.context('../src', true, /\.stories\.(js|tsx)$/), module);

그 다음에, docs 애드온과 @storybook/preset-create-react-app 프리셋을 설치해주겠습니다. 이 프리셋의 용도는 CRA로 만든 프로젝트에서 docs 를 만드는 과정에서 props 의 타입들을 추출 할 때 사용하는 react-docgen-typescript-loader 를 더욱 쉽게 적용하는 용도입니다.

yarn add --dev @storybook/preset-create-react-app @storybook/addon-docs
# 또는 npm install --dev @storybook/preset-create-react-app @storybook/addon-docs

설치를 하고난 다음에는 .storybook/presets.js 파일을 만들어서 다음과 같이 입력해주세요.

.storybook/presets.js

module.exports = [
  '@storybook/addon-docs/react/preset',
  {
    name: '@storybook/preset-create-react-app',
    options: {
      tsDocgenLoaderOptions: {}
    }
  }
];

src/stories 경로는 불필요하므로 제거해주세요.

이제 간단한 컴포넌트를 만들어서 storybook 작동이 제대로 이루어지는지 확인해봅시다.

src/MyComponent.tsx

import React from 'react';

export type MyComponentProps = {
  /** 아무 이름이나 입력해보세요. */
  name: string;
};

/** 별 의미 없는 예시 컴포넌트 */
const MyComponent = ({ name }: MyComponentProps) => {
  return <div>Hello, {name}</div>;
};

MyComponent.defaultProps = {
  name: 'Storybook'
};
export default MyComponent;

src/MyComponent.stories.tsx

import React from 'react';
import MyComponent from './MyComponent';

export default {
  component: MyComponent,
  title: 'MyComponent'
};

export const myComponent = () => <MyComponent name="Storybook" />;

myComponent.story = {
  name: 'Default'
};

다 작성하셨으면, yarn storybook (또는 npm run storybook) 명령어를 실행해주세요.

결과가 잘 나타났나요?

이제, 우리가 배웠던 것들 이 프로젝트에서도 동일하게 진행을 하시면 되겠습니다~

7. 유용한 Storybook 팁

리액트 라우터를 사용 할 경우

여러분이 만약 리액트 라우터를 사용하는 컴포넌트의 스토리를 작성하게 된다면, storybook-react-router를 사용해보세요.

해당 패키지를 설치 후 다음과 같이 스토리 파일에서 이를 불러온다음에

import StoryRouter from 'storybook-react-router';

StoryRouter를 스토리 파일의 decorators 부분에 넣고 나면 내부에서 Link 컴포넌트를 통해 이동을 하게 될 떄 다음과 같은 형식으로 액션 부분에 PUSH 가 나타나게 됩니다.

예시 링크: 링크: https://diligent-hearing.surge.sh/?path=/story/notelist--basic

반응형 디자인을 하는 경우

반응형 디자인이 필요한 컴포넌트를 개발 할 때에는 @storybook/addon-viewport 애드온을 사용해보세요.

이 패키지를 설치하고 나서 .storybook/addons.js 파일에서 다음 코드를 입력하여 애드온을 적용할 수 있습니다.

import '@storybook/addon-viewport/register';

그러면, 이렇게 Storybook 화면에서 viewport를 선택 할 수 있게 됩니다.

예시 링크: http://react-uikit-sample.surge.sh/?path=/story/components-dialog--dialog

추가적으로, emotion을 사용 할 때 media query를 사용하는 방법은 이 링크를 참고해보세요.

리덕스를 사용하고, 컨테이너 컴포넌트의 스토리를 작성 할 경우

리덕스를 사용 할 때 컨테이너 컴포넌트의 스토리를 작성 할 경우, 다음과 같이 Provider 에서 mock store를 사용하는 decorator를 직접 만들어서 적용하시면 액션이 디스패치 될 때 Storybook의 Actions 탭에서 확인 할 수 있습니다.

import React from 'react';
import { action } from '@storybook/addon-actions';
import { Provider } from 'react-redux';
import Container from './Container';


// mock store
const store = {
  getState: () => {
    return {
      todos: [
        {
          id: 1,
          text: 'Do Something',
          done: false
        }
      ]
    };
  },
  subscribe: () => {},
  dispatch: action('disptach')
};

const withReduxMockStore = (story: () => JSX.Element) => (
  <Provider store={store}>{story()}</Provider>
);


export default {
  title: 'components|Container',
  component: Container,
  decorators: [withReduxMockStore]
};

export const sample = () => <Container />

강의를 마치면서..

이번 강의를 통하여 여러분들은 Storybook을 활용하는 방법을 배우셨고, Storybook의 도움을 받아 나만의 디자인 시스템을 만드는 방법도 알아보았습니다.

추가적으로, npm에 패키지를 직접 등록하는 것도 알아보았죠.

디자인 시스템을 제대로 구축하고 나면 나중에 디자인/개발 공수를 많이 줄여줄 수 있고 사용자에게 일관적인 UI를 제공 하는 것에 큰 도움을 줍니다.

하지만 디자인 시스템을 구축하는 작업 자체가, 절대 쉬운 일은 아닙니다. 재사용 가능한 컴포넌트를 제대로 만들고, 문서화도 열심히 하려면 준비하는 시간이 분명히 오래 걸립니다. 추가적으로, 이 강의에서는 빠진 프로세스이지만, 디자인 시스템에서 사용하는 컴포넌트들에 대한 테스트 코드를 작성하는 것 또한 매우 중요합니다. (테스트 코드를 작성 할 때에는 React Testing Library)를 사용 하는 것을 추천드립니다.)

디자인 시스템을 만들기 위해서는 디자이너와 개발자의 긴밀한 협업이 필요합니다. 그리고 가장 중요한것은, 작업을 시작하는 것입니다. 풀타임으로 디자인 시스템을 작업해서 멋진 디자인 시스템을 만들어낼 수 있다면 좋겠지만, 현실적으로 모든 시간을 디자인 시스템 개발에만 쏟기엔 어려울 수도 있습니다 (물론 인적자원 및 주어진 시간이 충분하다면 가능 할 것입니다). 이 작업을 미루지 않고, 조그맣게 시작을해서, 주기적으로 작업을 하고 계속해서 개선해나가는 것이 중요합니다.

규모가 큰 프로젝트에서 일관적인 UI 를 제공하면서 브랜드 이미지의 통일화 하는 작업을 하고자 한다면 디자인 시스템을 만들어서 사용하는 것은 정말 탁월한 선택입니다. 하지만, 규모가 작은 프로젝트를 작업하거나, 아니면 관리자 대시보드처럼 수많은 사용자가 아닌 내부 인원이 사용하는 프로젝트를 만드는 경우라면, 디자인 시스템을 사용하는 것은 불필요한 시간을 너무 많이 잡아먹게 되어 독이 될 가능성도 있다는 것, 염두하시길 바랍니다.

만약 디자인 시스템 개발을 할 여유가 부족하다면 꼭 디자인 시스템을 만들지 않고, 라이브러리를 만들지 않더라도, 프로젝트에 Storybook을 적용하여 프로젝트에서 사용중인 몇몇 컴포넌트에 대하여 문서화를 하는 것도 프로젝트 퀄리티 향상에 큰 도움이 됩니다.

이 강의를 준비 할 수 있도록 프로그램을 마련해준 Facebook Innovation Lab에 감사를 드립니다. 그리고, 이 강의를 검수해주신 류지환님께 감사드립니다.

profile
CEO @ Chaf Inc. 사용자들이 좋아하는 프로덕트를 만듭니다.

4개의 댓글

comment-user-thumbnail
2019년 12월 20일

정말 좋은 글 감사드립니다.1!!

답글 달기
comment-user-thumbnail
2020년 2월 10일

덕분에 스토리북을 제대로 한번 써보게 되는 것 같습니다... 이 은혜 잊지 않겠습니다 선생님!!

답글 달기
comment-user-thumbnail
2020년 6월 18일

벨로퍼트님을 유튜브에서 처음알게 되고 무료강좌를 보다 인프런에서 나머지 부분 유료 강좌를 사서
강좌를 토대로 클래스 기반으로 포트폴리오 만들어 취업한지가 벌써 1년이 지났습니다.

1년간 일하면서 여유가 조금 생기니 디자인 관련 문서도 만들고싶고 타입스크립트도 해보고싶었는데 역시나 벨로퍼트님이 또 좋은 강좌를 써주셨내요.. 언제나 감사드립니다

현재 2020/06/18 이후 이 글대로 따라하시는 분들은 .storybook/main.js도 같이 생기실텐데요 그냥 삭제하시고 따라하시면 문제없습니다! 그리고 config.js는 윗분 댓글처럼 src/ 가 아닌 .storybook/ 에 만드시면 오류없이 잘 되실 것 같습니다!

답글 달기
comment-user-thumbnail
2021년 11월 19일

안녕하세요 좋은 글 보며 잘 따라하며 디자인시스템을 구축 중입니다.
질문 사항이 하나 있는데 스토리북을 구축하고 나서 다른 프로젝트에서 가져다 쓰려면
( 현재 cra가 아닌 스토리북 레포를 따로 구축하였고, 다른react 프로젝트에서 쓰려고 합니다. )
꼭 npm에 패키지를 등록한다음에 import 해서 사용해야 하는건가요?

storybook가동 시키면 copy code가 있긴한데 딱 버튼 컴포넌트만 나와서 이걸 어떻게 가져와서 써야하는건지 잘 모르겠어서 댓글 남깁니다. 답변 해주시면 정말 감사드립니다.

답글 달기