💕
후원
본문 바로가기
Web/Frontend

[라이브러리] 뚝딱뚝딱 UI 라이브러리 만드는 일기

by r4bb1t 2024. 6. 4.
반응형

이번 학기에 동아리에서 찬휘의 '나만의 작고 소중한 UI 라이브러리 만들기' 세션을 들으며 UI 라이브러리를 만들어볼 기회가 있었습니다. 전부터 만들어보고 싶다고는 생각했었는데 킹갓찬휘가 떠먹여준다? 당장 달려갔습니다.

일단 주 목적은 내가 쓸 것을 만들기였습니다.

번들러, UI 컴포넌트 개발 도구 선택과 세팅

우선 번들러는 우리가 js, jsx나 ts, tsx 등으로 작성한 여러개의 코드 파일들을 하나 또는 여러 개의 파일로 묶어주는 역할을 합니다. 이 과정에서 문자를 압축해서 코드 파일의 용량을 줄여주기도 하고 트리 셰이킹을 통해 안 쓰는 부분을 없애주기도 합니다. 가장 유명한 웹 번들러는 아무래도 Webpack일텐데요. 웹팩의 가장 큰 유용한 점 중 하나는 Hot Module Replacement입니다. 공식 문서에도 나와있듯 모든 종류의 모듈을 새로고침 할 필요 없이 런타임에 업데이트 할 수 있습니다. 소스코드를 수정하면 새로고침을 하지 않아도 바로 반영이 됩니다. 또, Code Splitting코드를 다양한 번들로 분할하고, 요청에 따라 로드하거나 병렬로 로드할 수 있도록 해줍니다. 바로 로드할 필요 없는 코드는 나중에 로드해서 로딩 속도의 개선을 도모할 수 있는 등의 장점이 있습니다.

하지만 이번 프로젝트에서 선택한 라이브러리는 Rollup입니다. 웹팩과의 주요 차이점은, 롤업은 모듈 호이스팅을 통해 모든 모듈들을 동일한 수준으로 끌어올려 번들링을 합니다. 라이브러리 만들 때 많이 쓴다고 하여 선택했습니다. 결과적으로 js로 컴파일된 파일 하나, 타입들이 정의된 d.ts 파일이 남게 됩니다.

처음에는 React + Vite로 세팅을 했습니다. 또 UI 컴포넌트 테스트를 위해 무거운 Storybook 대신 빠르고 간단한 Ladle을 선택했는데.. Next.js로 라이브러리 기반을 바꾸면서 결국 Storybook으로 가게 됩니다.

설정은 찬휘의 레포를 참고해주세요..

그 외에 자잘한 세팅들은 아래와 같습니다.

  • tailwind config를 export해서 preset을 만들어서 라이브러리를 가져다 쓰는 곳에서 적용할 수 있도록 합니다.
  • 각 컴포넌트들을 라이브러리의 진입점에서 export해줍니다.

무엇을 만들까

일단 제일 필요하고 자주 쓰는 컴포넌트부터 만들어보기로 했습니다. 모달, 토스트과 버튼인데요. 버튼이야 그냥 스타일 적용하면 되고.. 모달과 토스트는 전역에서 사용할 수 있게 하기 위해 Layout에 넣어두고 zustand로 state를 관리해서 어디서든 useAlert()로 사용할 수 있게 했습니다.

토스트와 모달

처음에는 실제로 써보면서 확인을 하기 위해.. npm에 배포를 해서 다운받아 썼는데요. 버전이 0.0.20이 넘어가자.. 이건 좀 아닌 것 같아서 로컬에 있는 파일들을 패키지로 쓰면서 체크하는 게 낫겠다 싶었습니다.

npm 배포는

{
...
  "name": "@r-4bb1t/rabbit-ui",
  "private": false,
  "version": "0.0.44",
  "type": "module",
  "author": "r-4bb1t",
  "main": "dist/src/index.js",
  "typings": "dist/src/index.d.ts",
  "description": "Rabbit UI: UI components for Next.js with Tailwind CSS",
  "repository": {
    "type": "git",
    "url": "https://github.com/r-4bb1t/rabbit-ui.git"
  },
...
}

package.json에 위와 같이 정보를 작성해주고

npm publish --access=public

npm 로그인 된 상태에서 위의 라인을 터미널에 치면 됩니다.

로컬 파일을 패키지로 쓰려면.. 사용할 곳의 package.json에

{
  ...
  "dependencies": {
    "@r-4bb1t/rabbit-ui": "로컬의 dist 주소",
    ...
  },
  "pnpm": {
    "overrides": {
      "@r-4bb1t/rabbit-ui": "로컬의 dist 주소"
      ...
    }
  },

이런 식으로 해주면 됩니다. 짱 편했어요.

Next.js와 Storybook으로 이주

일단 제가 많은 프로젝트를 Next.js로 만들기 때문에, 위와 같이 작성을 하면 Layout으로 감쌀 경우 내부에 server component를 쓸 수가 없게 됩니다. 모달과 토스트가 client component라서,, 그걸 명시를 해주고 싶었어요. 그래서 기반을 Next.js로 바꾸고,,

import preserveDirectives from "rollup-preserve-directives";

const sourceOptions: RollupOptions = {
  ...
  output: { ..., preserveModules: true },
  plugins: [..., preserveDirectives()]
  ...
}

rollup-preserve-directives 플러그인을 활용해 'use client' 등의 directives를 냅두도록 합니다.

그리고... preserveModules가 false이면(default) 파일을 다 하나로 합칩니다. 당연함. 근데 이렇게 하면 모든 것들이.. 클라이언트 컴포넌트가 되어버립니다.. 결국 파일 합치기의 이점을 포기하고 preserveModules를 true로 했습니다.

Next.js로 바꾸고 ladle도 다시 세팅을 하다가.. 공식 문서를 참고해봐도 잘 작동이 안되는 것 같아서 그냥 Storybook으로 이주했습니다. 빌드 완전 오래 걸림.

Storybook

뭔가 얼렁뚱땅이지만.. 아무튼 열심히 배포까지 해놓았고.. 계속 써보면서 개선하고 있습니다. 재밌다.

https://ui.r4bb1t.dev/

 

@storybook/cli - Storybook

 

ui.r4bb1t.dev

https://www.npmjs.com/package/@r-4bb1t/rabbit-ui

 

@r-4bb1t/rabbit-ui

Rabbit UI: UI components for Next.js with Tailwind CSS. Latest version: 0.0.44, last published: 2 days ago. Start using @r-4bb1t/rabbit-ui in your project by running `npm i @r-4bb1t/rabbit-ui`. There are no other projects in the npm registry using @r-4bb1t

www.npmjs.com

 

 

반응형

댓글