그림 그리는 개발자
  • github 에 내가 만든 react frontend package 배포하기
    2023년 07월 22일 13시 31분 00초에 업로드 된 글입니다.
    작성자: 루루개발자

    안녕하세요. 루루개발자 입니다.

     

    이번 시간에는 github action 을 활용하여 github package 저장소에 npm package 를 배포하는 방법에 대해 기술해보고자 합니다. 본 글에서는 typescript 기반의 react 와 프론트엔드(브라우저)에서 사용되는 패키지를 기준으로 하며 레포지토리의 패키지 개발 코드들이 src 폴더 밑에 있다고 가정하고 배포하는 방법을 설명하기 때문에 이 점 참고해주세요. :)

     

    1. personal access token 발급 받기

    github action 에서 github package 저장소로 패키지를 publish 하기 위해서는 해당 권한이 있는 토큰이 필요하므로 아래 과정을 참고하여 토큰을 발급받아 주세요.

    • 토큰의 이름은 “PACKAGE_PUBLISH_KEY” 로 설정하고(임의로 지정해도 되는 부분이지만 여기서는 이후 설명의 편의를 위해 이렇게 명명하겠습니다.) write:packages 에 체크를 한 후 Generate token 버튼을 클릭합니다.

    • 생성된 token 을 복사해 둡니다.

     

    2. 레포지토리에 secret key 셋팅하기

    토큰을 발급 받았으면 이제 해당 토큰을 패키지 레포지토리에 설정해주면 됩니다.

    • https://github.com/유저명/레포지토리명/settings/secrets/actions 에 접속합니다. (유저명, 레포지토리명은 본인 환경에 맞게 수정하여 접근해주세요.)
    • “New repository secret” 버튼을 클릭합니다.
    • Name 은 “PACKAGE_PUBLISH_KEY” 으로, Secret 은 이전 단계에서 복사한 token 을 붙여넣고 등록합니다.

     

    3. 레포지토리 루트에 index.ts 파일 생성하기

    다음과 같이 레포지토리 루트 경로에 index.ts 파일을 생성하고 내보내고 싶은 모듈을 export 하는 문을 작성해줍니다.

    export * from './src/components/my-component';
    export * from './src/hooks/my-hook';
    // ...

     

    4. 번들링을 위한 패키지 설치하기

    내보낼 모듈들과 연관 된 파일들을 하나로 묶기 위해 esbuild 와 esbuild-css-modules-plugin 패키지를 설치합니다.

    npm i -D esbuild esbuild-css-modules-plugin

     

    5. package.json 수정하기

    패키지 배포를 위해 package.json 의 아래 각 항목 값들을 다음과 같이 수정해주어야 합니다.

    {
      ...
      // github 개인 계정이신 경우 스코프명은 github 계정 이름으로 지정하시면 됩니다.
      "name": "@스코프명/패키지명",
      
      // private 는 false 로 지정해줍니다.
      "private": false,
    
      // 아래와 같은 스크립트를 추가합니다.
      // build.esbuild.js 에는 번들링 관련된 옵션들이 작성되어 있습니다. 본 블로그 글의 하단에 해당 내용에 대해 기술합니다.
      // tsconfig.package.json 에는 본 패키지를 내보낼 때 사용되어야 할 빌드 옵션이 작성되어 있습니다. 본 블로그 글의 하단에 해당 내용에 대해 기술합니다.
      "script": {
        "build": "node ./build.esbuild.js",
        "build:tsc": "tsc --project ./tsconfig.package.json"
      },
    
      // 본 레포지토리의 진입점이 되는 경로를 작성합니다.
      "main": "index.ts",
      
      // 본 레포지토리의 패키지를 배포할 저장소 정보를 작성합니다.
      "publishConfig": {
        "registry": "https://npm.pkg.github.com"
      },
      
      // 본 레포지토리의 git 저장소 주소를 작성합니다.
      "repository": "...",
      
      // 본 패키지는 리액트에서 사용되는 패키지이므로 본 패키지를 사용하는 곳에서 리액트와 관련된 라이브러리가 설치 되어야 함을 알려주기 위해 다음과 같이 peerDependencies 를 추가 작성합니다.
      // 아래에 기재된 버전들은 본인 레포지토리에 설치된 패키지들의 버전에 맞춰 작성해주시면 됩니다.
      // 예를 들어 depedencies 에 "react": "18.2.0" 으로 지정되어 있다면 peerDependencies 에는 "react": "^18.2.0" 으로 작성해주시면 됩니다.
      "peerDependencies": {
        "@types/react": "^dependencies 에 설치된 해당 패키지의 버전",
        "@types/react-dom": "^dependencies 에 설치된 해당 패키지의 버전",
        "react": "^dependencies 에 설치된 해당 패키지의 버전",
        "react-dom": "^dependencies 에 설치된 해당 패키지의 버전"
      }
      ...
    }

     

    6. build.esbuild.js 파일 작성하기

    번들링에 사용할 패키지는 esbuild 이며 이와 관련된 내용을 레포지토리 루트에 build.esbuild.js 파일을 생성하고 아래와 같이 작성합니다.

    const esbuild = require("esbuild");
    const cssModulesPlugin = require("esbuild-css-modules-plugin");
    
    esbuild.build({
      entryPoints: ["index.ts"],
      target: ['es5', 'es6', 'es2017'],
      bundle: true,
      sourcemap: false,
      minify: true,
      format: 'cjs',
      platform: 'browser',
      jsx: 'automatic',
      outfile: "index.js",
      tsconfig: "./tsconfig.package.json",
      treeShaking: true,
      external: ['react-dom', 'react'],
      plugins: [
        cssModulesPlugin({
          inject: true,
          localsConvention: 'dashes',
          filter: /\.module?\.css$/i,
          v2: false,
        }),
      ],
    });

     

    7. tsconfig.package.json 파일 작성하기

    루트 경로에 tsconfig.package.json 파일을 생성하고 빌드 시 사용할 typescript 환경설정 내용을 작성합니다.

    {
      "compilerOptions": {
        "target": "es6",
        "lib": ["dom", "dom.iterable", "esnext"],
        "declaration": true,
        "declarationDir": "lib/src",
        "emitDeclarationOnly": true,
        "allowJs": true,
        "skipLibCheck": true,
        "strict": true,
        "forceConsistentCasingInFileNames": true,
        "esModuleInterop": true,
        "module": "esnext",
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "isolatedModules": true,
        "jsx": "preserve",
        "incremental": true,
        "paths": {
          "@/*": ["./src/*"]
        }
      },
      "include": ["next-env.d.ts", "src/hooks/**/*.ts", "src/hooks/**/*.tsx", "src/components/**/*.ts", "src/components/**/*.tsx"],
      "exclude": ["node_modules"],
    }

     

     

    8. .github/workflows/package-deploy.yml 파일 작성하기

    레포지토리 루트 경로에서 .github/workflows/package-deploy.yml 파일 생성 후 아래와 같이 배포 코드를 작성해줍니다.

    name: package-deploy
    
    on:
      push:
        tags:
          - v*
    
    jobs:
      publish-npm-registry:
        runs-on: ubuntu-latest
        permissions:
          contents: read
          packages: write
        steps:
          - uses: actions/checkout@v2
          - uses: actions/setup-node@v1
            with:
              node-version: 18
              registry-url: https://npm.pkg.github.com/
          - run: npm install
            env:
              NODE_AUTH_TOKEN: ${{secrets.PACKAGE_PUBLISH_KEY}}
          - run: npm run build
          - run: npm run build:tsc
          - run: mv ./index.ts ./index.d.ts
          - run: rm -rf ./src
          - run: rm -rf ./public
          - run: rm -rf ./.github
          - run: mv ./lib/src ./src
          - run: npm publish
            env:
              NODE_AUTH_TOKEN: ${{secrets.PACKAGE_PUBLISH_KEY}}

     

    9. github 에 push 후 "v"로 시작하는 새로운 태그로 새로운 릴리즈 버전을 생성하기

    패키지 개발이 완료 된 상태라면 해당 코드들을 커밋 후 github 저장소로 push 합니다. 그리고 아래 사진 처럼 새로운 버전을 release 합니다.

     

    10. 패키지 빌드 및 배포완료

    그러면 이제 앞서 작성한 ".github/workflows/package-deploy.yml" 을 기반으로 github action 에서 빌드 및 배포가 시작됩니다. 배포가 완료되면 다음과 같이 패키지가 정상적으로 생성된 것을 확인하시면 됩니다.

     

    11. github 에 배포된 패키지를 설치해 사용하기

    github 에 배포되어 있는 패키지를 레포지토리에 설치하기 위해서는 패키지 접근 권한이 있는 토큰이 필요합니다. 패키지를 이용하고자 하는 레포지토리의 루트 경로에 .npmrc 파일을 생성하여 다음과 같이 작성해줍니다.

    @스코프명:registry=https://npm.pkg.github.com/
    //npm.pkg.github.com/:_authToken=깃허브access토큰

    위와 같이 작성하면 특정 scope 에 해당하는 패키지는 github 패키지 저장소에서 다운로드 받을 수 있도록 설정할 수 있습니다. 토큰은 본 게시글의 1번 단계에서 진행했던 것처럼 패키지를 읽을 수 있는 권한으로 체크하신 후 토큰을 생성하시면 됩니다. 이제 .npmrc 작성이 완료 되었다면 아래 명령어로 github 에 등록된 패키지를 설치할 수 있습니다.

    npm i @스코프명/패키지명

     

     

     

    지금까지 Typescript 환경의 리액트 기반 패키지를 github 에 배포하는 과정이었습니다. 

    궁금하신 점이나 잘못된 부분이 있다면 댓글로 남겨주세요~!

    감사합니다. :)

    댓글