[FE쥬니어의 Design System] 01. Personal Design System, Storybook, Vite로 환경 설정하기

gitgitWi's TIL·2022년 3월 2일
1

Storybook + React로 DesignSystem/ComponentLibrary 만드는 튜토리얼은 이미 블로그, Youtube에 널려있다

Airbnb, GitHub 등 개발팀에서 만든 Storybook은 물론이고, GitHub가 공개된 경우도 있다 (아래 references 참고)

👉  구현 중인 GetIt-UI GitHub 보기

👉  Hashnode에서 보기

Motivation

  • 요즘 차트 컴포넌트 구현을 Storybook 기반으로 진행중(zum-stock-line-stories)인데, 생각보다 엄청난 생산성 향상을 맛보며 재미를 느낌

    • 별도의 페이지를 구성하지 않아도 컴포넌트 구현 결과를 HMR로 볼 수 있음 (이건 당연한 거!)

    • 개발자 도구 들어가서 ➡️ 메뉴를 클릭하고 ➡️ 뭔가를 조정해야 하는 수고들을 덜어줌!

    • Docs로 한번에 여러 렌더링 상태 확인 가능

    • addon 생태계가 활성화되어있음

      • Jest, Cypress 등 다양한 툴과의 통합
    • Storybook을 따로 빌드, 배포 가능

      • 현재까지 개발 진행상황 공유 가능

      • 색상, 크기, 데이터값 등 속성들을 controls로 바꿔서 바로 확인 가능 👉 디자이너/기획자와의 보다 빠른 소통 가능할 듯?!


  • 거의 1년째 방치 중인 개인 블로그는 물론이고, 셋팅만 열심히 했던 개인 프로젝트들 빠르게 완성도를 높이기 위해 디자인 시스템을 만들어보자

    • 단기적으로 1년 정도는 컴포넌트 라이브러리 구축 위주 방향이 될 듯, 아무래도 디자인/UX에 대한 지식이 없기 때문
    • 장기 프로젝트로 디자인 시스템으로 발전시켜 나가자

  • 회사 업무에 적용하기 전 다양한 테스트를 위한 도구로 사용할 수 있음
    • 하고 싶은 거 다하자!!
    • 얼마전 당근마켓 프론트엔드 개발자 라이브 QnA 세션 에서 얻은 인사이트
      • 회사 코드를 포트폴리오로 사용할 수는 없으니 유사한 구현 내용을 개인 GitHub에 올려놓는 것도 방법이다!

Design Patterns & Techs I Used

  • Atomic Design Pattern & Monorepo

    • 기본적으로 컴포넌트 라이브러리이기 때문에, atoms, molecules, organisms 정도까지만 하면 될 듯

      • 이 단계에 따라 각각의 패키지 구성; atoms/button, atoms/text
    • 디자인 시스템 중 단일 Repo로 구성하는 경우도 많지만, 추후 Svelte, Solid 등 다양한 프레임워크/라이브러리 및 rollup, esbuild 등 다양한 빌드 툴 사용해볼 수 있도록 Monorepo로 구성

    • Yarn berry PnP 모드에서 workspace 플러그인 사용

      getit-ui/
      ┣ atoms/ # atom packages
      ┃ ┣ button/
      ┃ ┃ ┣ src/
      ┃ ┃ ┣ package.json
      ┃ ┃ ┣ tsconfig.json
      ┃ ┃ ┣ tsconfig.node.json
      ┃ ┃ ┗ vite.config.ts
      ┃ ┗ text/
      ┃   ┣ src/
      ┃   ┣ package.json
      ┃   ┣ tsconfig.json
      ┃   ┣ tsconfig.node.json
      ┃   ┗ vite.config.ts
      ┣ molecules/ # molecules packages
      ┣ stories/ # storybook package
      ┃ ┣ .storybook/
      ┃ ┃ ┣ main.ts
      ┃ ┃ ┗ preview.ts
      ┃ ┣ src/
      ┃ ┃ ┣ Introduction.stories.mdx
      ┃ ┃ ┣ react-app-env.d.ts
      ┃ ┃ ┗ setupTests.ts
      ┃ ┣ .gitignore
      ┃ ┣ package.json
      ┃ ┗ tsconfig.json
      ┃ # root configs
      ┣ .editorconfig
      ┣ .eslintignore
      ┣ .eslintrc.js
      ┣ .gitignore
      ┣ .pnp.cjs
      ┣ .pnp.loader.mjs
      ┣ .prettierrc
      ┣ .yarnrc.yml
      ┣ Dockerfile.dev
      ┣ README.md
      ┣ package.json
      ┣ tsconfig.components.json
      ┣ tsconfig.json
      ┗ yarn.lock

  • Storybook

    • 구현된 컴포넌트들 시각 테스트
    • 회귀, E2E 등 다양한 테스트, 문서화
    • 별도의 전용 패키지(stories)를 만들어서 실행


  • CSS(SCSS) Module

    • 개인적으로 CSS를 활용할 때 가장 선호하는 방식

    • styled-component/emotion 보다 CSS 그 자체를 사용하면서, JS 방식으로 className 적용을 컨트롤 할 수 있음

    • 특히 이번 대선 차트 구현할 때 이점을 크게 맛보게 되었는데, IE에서 grid(-ms-grid)가 생각대로 컨트롤 하기 어렵다는 점 때문에, IE 전용 클래스를 따로 만들어 userAgent에 따라 분기처리해 적용함

      // 모던 브라우저 클래스
      .line {
        @extend .line-default;
        display: grid;
        grid-template-columns: 13px minmax(36px, auto) minmax(46px, auto);
      }
      
      // IE 전용 클래스
      .line-ie {
        @extend .line-default;
        display: -ms-flexbox;
      
        div {
          margin-right: 5px;
        }
      
        p {
          width: 47px;
        }
      }
      // line 컴포넌트 (VanillaJS)
      classNames: [IS_IE ? styles['line-ie'] : styles['line'], ...classNames];
      // ...

Problem & Solutions

Vite 라이브러리 모드 빌드 -> 모노레포에서 사용시 CSS를 가져오지 않는 문제?

Problem

  • HTML 파일을 생성하는 게 아닌, JS로 컴포넌트 렌더링 로직만 만드는 것

  • 일반적인 페이지를 빌드하는 경우, Webpack 등 번들러가 HTMLlink 태그를 자동삽입하고, 렌더링시 스타일을 반영함

  • 그런데 라이브러리 모드에서 빌드시 JS에 CSS Module 클래스명만 가져오고, CSS 파일(import 'styles.css')을 가져오지 않음

  • 다른 패키지에서 사용시 스타일 적용 안됨


Solution

  • vite-plugin-css-injected-by-js 사용

    • vite.config.ts에서 플러그인 추가
    import cssInject from 'vite-plugin-css-injected-by-js';
    
    export default defineConfig({
      plugins: [react(), cssInject()],
    
      /** 기타 설정 */
    });
    • 빌드시 아래와 같이 style 태그 생성 로직을 생성, 빌드된 파일 상단에 삽입

      • 동일 컴포넌트를 여러개 호출하더라도 하나의 style 태그만 생성함

      • 근데 이렇게 되면 CSS-in-JS를 쓰는 방식과 성능면에서 차이가 없어질 수도 있지 않을까하는 의문이..

Storybook 전용 stories 패키지에서 Vite 사용시 빌드 오류

Problem

  • 현재 각각의 컴포넌트 패키지 + Storybook 전용 패키지가 있는 상황
  • 컴포넌트 패키지들이 이미 Vite를 사용하고 있고, (왠만하면) Webpack 보다는 Vite가 빌드 타임이 짧기 때문에 Vite 빌더를 써보려고 시도 함
  • 문제는 Yarn berry 환경에서 Vite 빌더가 의존성 제대로 못 찾고 빌드가 안됨

Solution

  • 아쉽지만 stories 패키지만 빌더를 CRA + Webpack5로 지정해 사용 중
  • 내 생각에 베스트는, Storybook 전용 패키지를 별도로 분리하지 않고, 각각의 컴포넌트 패키지에서 story 파일를 만들어서 root에서 preview를 실행하도록 하는 것
    • 다만 Monorepo 구조의 root에서는 뭔가 설정하기가 까다로움
    • 좀더 연구해봐야 할 듯..?
    • 한편 패키지를 분리했기 때문에, 다른 패키지에서 import 했을 때 잘 되는지 확인 할 수 있다는 장점은 있는 듯


References

Design System Overview

Real-World Cases

profile
가볍게 TIL 남기는 velog, 꾸준히 성장하는 개발자

0개의 댓글