NPM 라이브러리 배포하기

BangDori·2024년 5월 25일
2

✨ 이전 포스팅

웹에 아이폰을 띄워보자

Pennyway 프로젝트에서 웹뷰를 제작하면서, 아이폰 뷰 내에서 웹뷰를 보는것이 개발 생산성이 향상될 것 같아 구현을 하게 되었다.

근데 웹뷰 뿐만 아니라 웹앱을 구현하는 사람들의 입장에서 내가 구현한 기능이 도움이 될 것 같다고 생각하여, 이를 라이브러리로 배포하고자 결심하게 되었다!

Package.json

우선 NPM 라이브러리를 배포하기 위해서는 초기 설정이 필요하다. 우선 package.json을 나는 다음과 같이 만들었다.

{
  "name": "react-iphone-layout", // 라이브러리명
  "private": false, 
  "version": "1.0.0", // 라이브러리 버전
  "type": "module", // ES 모듈임을 나타내는 속성
  "description": "iPhone layout in browser on web", // 라이브러리 설명
  "author": "bangdori <bangdori8865@gmail.com>", // 라이브러리 저자
  "contributors": [ // 라이브러리 기여자
    "legitgoons <cksxkr5193@naver.com>"
  ],
  "license": "MIT", // 프로젝트의 라이센스 종류 중 하나로 MIT 라이센스는 매우 관대한 오픈 소스 라이센스
  "main": "dist/iphone-layout.cjs.js", // CommonJS 방식으로 빌드된 메인 파일의 위치
  "module": "dist/iphone-layout.es.js", // ES 모듈 방식으로 빌드된 메인 파일의 위치
  "types": "dist/types/index.d.ts", // 타입스크립트 타입 정의 파일의 위치
  "repository": { // 저장소의 종류 및 주소
    "type": "git",
    "url": "https://github.com/BangDori/iPhone-layout"
  },
  "bugs": { // 버그 보고를 위한 URL 및 이메일
    "url": "https://github.com/BangDori/iPhone-layout/issues",
    "email": "bangdori8865@gmail.com"
  },
  "homepage": "https://github.com/BangDori/iPhone-layout", // 라이브러리의 홈페이지 URL
  "keywords": [ // 라이브러리 관련 키워드로 npm 레지스트리 SEO
    "iPhone",
    "webview",
    "webapp"
  ],
  "exports": { // 패키지 내보내기 설정
    ".": {
      "module": "./dist/iphone-layout.es.js", // 모듈 방식으로 내보낼 파일
      "import": "./dist/iphone-layout.es.js", // ES 모듈을 사용할 때의 기본 파일
      "default": "./dist/iphone-layout.cjs.js", // CommonJS 모듈을 사용할 때의 기본 파일
      "types": "./dist/types/index.d.ts" // 타입 정의 파일
    }
  },
}

현재 package.json을 확인해보면, ES, CommonJS 방식 등 으로 구성되어 있는 것을 확인할 수 있습니다. 패키지를 다운받고 사용하는 사용자의 입장에서 자신의 환경에 맞는 모듈 시스템을 선택할 수 있도록 하는 것이 중요하다고 생각하여 위와 같이 설정하였습니다.

구조

어떤 식으로 코드를 작성하고, 어떤 식으로 배포해야 할 지 참고할 자료를 찾기 위해 react-toastify 라이브러리의 레포를 살펴보았다.

각 폴더의 역할을 살펴보자.

📂.github // CI/CD 파이프라인의 workflow를 담당하는 폴더
📂.husky // Git hooks를 담당하는 폴더 
📂cypress/support // E2E 테스트를 담당하는 폴더
📂playground // 라이브러리를 배포하기 위해 테스트할 폴더
📂scss // 애니메이션, 변수 기타 스타일 등을 담담당하는 폴더 
📂src // ✨ 실제 라이브러리가 배포되는 entry

라이브러리를 배포하기 이전에 테스트하기 위해서는 npm에 임시적으로 업로드하는 것이 아닌, tgz 파일로 압축한 후 로컬에 있는 tgz 압축 파일을 설치해서 사용하면 된다. 단계는 다음과 같다. (나는 yarn을 사용했기에, yarn 커맨드를 기준으로 작성하겠다.)

  1. src 폴더를 build 한다.
    • yarn build
  2. build 파일을 tgz 파일로 압축한다.
    • yarn pack
  3. tgz 파일을 playground 폴더에서 설치하고, 실행하여 정상적으로 동작하는지 테스트한다.
    • yarn add ./(압축파일명).tgz -D
    • 나는 dev 환경에서 사용하기 위한 라이브러리를 만들고 있기 때문에 -D 옵션을 추가하였다.
    • 이때 중요한 점이 있는데, 라이브러리를 테스트할 때 항상 yarn cache clean을 해줘야한다. 그렇지 않으면 기존에 남아있는 cache data로 인해 라이브러리의 변경된 사항을 추적하지 못하는 상황이 발생한다. (실제로 이거때문에 고생했다..)

나의 경우에는 playground 폴더의 역할이나 존재 이유에 대해 생각하지 않고, 새로운 프로젝트 폴더를 만들어서 진행했다.. 라이브러리 배포까지 하고 나서 생각해보니 playground의 역할이 크게 와닿는다. 다음부터는 꼭 playground에서 테스트하면서 해야겠다..

src

src 폴더 내부에 아래와 같이 배포할 정보를 설정해두었다.

기본적으로 다른 컴포넌트들이나 이런건 일반적으로 작성하면 되는데 가장 중요한 것이 번들러의 진입 지점에서 export를 해주는 것이 중요하다!

// src/index.ts
export { IPhoneLayout } from "./lib";

// vite.config.ts
export default defineConfig({
  plugins: [
    react(),
    dts({ insertTypesEntry: true, tsconfigPath: "./tsconfig.json" }),
  ],
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.ts"),
    },
    // ...
  }
})

위와 같이 entry 지점에서 export를 해주면, 실제로 라이브러리를 배포하였을 때 다음과 같이 export 하는 것을 확인할 수 있다.

이렇게 설정해주면 우리가 만든 라이브러리를 이제 우리가 사용할 수 있게 된다!

import { IPhoneLayout } from "react-iphone-layout";
import "react-iphone-layout/dist/ReactIPhoneLayout.css";

import ReactDOM from "react-dom/client";
import "./index.css";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <IPhoneLayout>
    Hello World
  </IPhoneLayout>,
);

라이브러리를 npm에 배포하기

라이브러리를 개발하고 환경 설정까지 완료했다면, 이제 남은 건 npm에 배포하는 것이다. 이 과정은 npm에 로그인하고 라이브러리를 publish하는 간단한 단계로 이루어져 있으니, 곧 있으면 우리가 만든 라이브러리(내 자식)를 세상에 보여줄 수 있다.

1. npm 로그인

먼저, npm에 로그인해야 합니다. 터미널을 열고 아래 명령어를 입력합니다.

$ npm login

그러면 링크가 나타나고, 해당 링크로 연결된다. 링크에서 보안 문자르 입력하면 로그인이 완료된다.

2. npm 배포

이제 라이브러리를 npm에 배포할 준비가 되었습니다...!!! 터미널에서 아래 명령어를 입력해주세요.

$ npm publish

이 명령어를 실행하면 npm에 라이브러리가 업로드되고, 배포가 완료된다!

내가 만든 내 자식 😁

라이브러리 배포 후기

지금까지 번들러 도구를 사용하여 번들링을 할 때 assets를 어떻게 관리하고, minify를 어떻게 할 것인지에 대해 크게 고민을 해 본 경험이 없는 것 같다.

프론트엔드 개발을 할 때 항상 UX를 고민하며 프로젝트를 진행했던 것 처럼 라이브러리를 제작하는 입장에서 이 라이브러리를 사용해주는 개발자의 입장에서 어떤 기능이 도움이 될까를 끊임없이 고민했던 것 같다. 환경에 종속되지 않게 하기 위해 CommonJS, ES 환경에서도 사용할 수 있게 하였다!

라이브러리 배포가 되게 막막하고 어렵게만 느껴졌는데, 참고 자료가 많아 도움을 받을 수 있었다. 아직까지 minify가 제대로 적용되지 않는 것 같기도 하고, 자동화, 최적화에서 부족한 부분이 많이 느껴져서 이를 천천히 적용할 계획이다!

라이브러리 배포를 위해 많은 도움을 주신 의찬님 정말 감사합니다!

참고

profile
Happy Day 😊❣️

0개의 댓글