GitHub Package Registry로 비공개 NPM 패키지 배포하기

2025. 4. 7. 19:04Dev_etc/Git

by HITS-AI

 

 

왜 GitHub Package Registry를 선택했는가?

 

기존에는 내부 라이브러리를 공유하기 위해 SSH 주소를 통해 로컬 설치하는 방식을 사용했지만, 다음과 같은 이유로 GitHub Package Registry 기반 배포로 전환하였습니다-

  • 버전 관리의 명확성: Git 태그 기반 버저닝으로 변경 이력 추적이 명확
  • 설정의 간편함: GitHub Action을 통한 배포 자동화 가
  • 설치 속도 및 안정성: CDN 캐싱과 병렬 처리 덕분에, git+ssh 방식에 비해 설치 속도가 빠르고 안정적 (17s -> 13s)

package.json 설정

git package에 배포하기 위해서는 라이브러리의 package.json에 name, version, publishConfig 값을 지정해줘야 합니다.

// package.json
{
  "name": "@hits-ai/hits-ngl",
  "version": "1.0.0", //태그 기반으로 배포할 경우, 임의의 version명 지정.
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/"
  }
}​

 

name은 반드시 GitHub 조직 이름(@hits-ai)을 prefix로 포함해야 하며, publishConfig.registry는 npm.pkg.github.com으로 지정해야 합니다.

 


배포 방식

위 설정한 package.json을 기반으로 npm에 배포하는 두 가지 방법을 소개해보겠습니다.

 

1. GitHub Action으로 배포 자동화

2. 수동 배포

 

GitHub Actions으로 배포 자동화

태그 패턴

저희 프로젝트는 태그 기반 배포 자동화 aciton을 적용했습니다.

 

 .github/workflows/publish.yml
name: Build and Publish on Tag

on:
  push:
    tags:
      - "hits-ngl/v[0-9]+.[0-9]+.[0-9]+-mod.[0-9]+" //hits-ngl/v2.4.0-mod.0 -> 2.4.0-mod.0 으로 배포

jobs:
  build-and-publish:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Set up Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "18"
          registry-url: "https://npm.pkg.github.com"

      - name: Install dependencies
        run: npm install

      - name: Extract version from tag
        id: version
        run: |
          REF=${GITHUB_REF#refs/tags/hits-ngl/}
          VERSION=${REF#v}
          echo "version=$VERSION" >> "$GITHUB_OUTPUT"

      - name: Inject version into package.json
        run: |
          VERSION=${{ steps.version.outputs.version }}
          jq --arg v "$VERSION" '.version = $v' package.json > temp.json && mv temp.json package.json

      - name: Build library
        run: npm run build-min

      - name: Publish to GitHub Packages
        run: npm publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

 

build-min은 사전 정의된 빌드 스크립트입니다. 환경에 맞게 조정해 주세요.

 

해당 액션을 통해

main에 병합 후 배포를 희망하는 커밋에 태그를 달아주면 자동으로 빌드/배포 자동화가 진행됩니다.

 

수동 배포

1. 버전 수정

수동 배포에서는 pacakge.json의 version에 실제로 배포될 version을 지정해줘야 합니다.

"version": "2.4.0-mod.0"

 

2. 빌드 

npm run build-min # build-min은 사전 정의된 빌드 스크립트입니다. 환경에 맞게 조정해주세요.

 

3. 로그인 (최초 1회)

npm login --registry=https://npm.pkg.github.com

또는 .npmrc 설정:

@hits-ai:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=ghp_xxx...

 

4. 패키지 배포

npm publish

설치 방법 (로컬 또는 배포 환경)

위 과정을 통해 npm에 패키지 배포를 완료했고, 이제 배포된 비공개 라이브러리를 어떻게 프로젝트에 설치하는지 소개해보겠습니다-!

 

우선 패키지 영향범위가 있는 스코프에 .npmrc 파일을 생성하고, 아래 내용을 기입해 줍니다.

@hits-ai 하위의 패키지 들은 해당 주소로 접근하겠다는 뜻입니다-
@hits-ai:registry=https://npm.pkg.github.com/

 

해당 파일에 아래처럼 토큰을 주입해도 되지만, 토큰을 노출시키는 게 꺼림칙해서 토큰을 따로 주입하기로 했습니다.

@hits-ai:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=ghp_xxx...

 

이제 로컬/배포환경에서 각자 토큰을 주입하고 설치하도록 설정해 주겠습니다.

로컬

  1. 토큰 발급
    https://github.com/settings/tokens 에서 read:packages 권한이 있는 personal access token(PAT)을 생성
  2. npmrc 등록 스크립트
설치 전에 npm 인증을 확인하여 인증이 필요하면 토큰을 입력받고, 필요 없으면 그대로 설치를 진행하는 스크립트를 적용해 설치하고 있습니다.
"scripts": {
  "setup-npm-and-install": "npm run setup-npm && pnpm i",
}
#!/bin/bash

NPMRC="$HOME/.npmrc"
REGISTRY_URL="https://npm.pkg.github.com"
NAMESPACE="@hits-ai"

check_login(){
  npm whoami --registry="$REGISTRY_URL" > /dev/null 2>&1
}

save_token(){
  if [ ! -f "$NPMRC" ]; then
    touch "$NPMRC"
    echo "'$NPMRC' Created"
  fi

  if grep -q "$REGISTRY_URL" "$NPMRC"; then
    echo "Invalid token"
    sed -i.bak "/$NAMESPACE:registry=$REGISTRY_URL/d" "$NPMRC" 2>/dev/null
    sed -i.bak "/\/\/npm.pkg.github.com\/:_authToken=/d" "$NPMRC" 2>/dev/null
  fi

  echo -n "GitHub Personal Access Token: "
  read -s TOKEN
  echo

  echo "" >> "$NPMRC"
  echo "$NAMESPACE:registry=$REGISTRY_URL" >> "$NPMRC"
  echo "//npm.pkg.github.com/:_authToken=$TOKEN" >> "$NPMRC"

  echo "Token saved to ~/.npmrc"
}


if check_login; then
  echo "Login Success"
  exit 0
fi

MAX_TRY=3
for ((i = 1; i <= MAX_TRY; i++)); do
  save_token
  if check_login; then
    echo "Login Success"
    exit 0
  else
    echo "Login Failed. ($i/${MAX_TRY})"
  fi
done

배포 환경

기본 환경 (Docker x)

도커환경이 아닌 기본 환경에서는,

배포 액션에 다음과 같이 패키지 설치 전에 Git에 설정되어 있는 인증 토큰을 주입시켜 인증하고 설치를 진행합니다.

# .github/workflows/cd.yml
- name: Authenticate with GitHub Packages
  run: |
    echo "//npm.pkg.github.com/:_authToken=${{ secrets.GITHUB_TOKEN }}" > ~/.npmrc

- name: Install dependencies
  run: pnpm install

Docker 환경

도커 환경에서는 도커파일 내부에서 인증을 해줘야 합니다.

1. git action 파일에서 도커에 환경 변수로 토큰을 지정해 줍니다.

# .github/workflows/cd.yml
file: "apps/Dockerfile"
build-args: |
  GITHUB_PAT=${{ secrets.PAT }}

 

2. docker 파일에서 넘겨받은 토큰으로 인증 후 설치 진행

# apps/Dockerfile
ARG GITHUB_PAT
...

RUN echo "//npm.pkg.github.com/:_authToken=${GITHUB_PAT}" > ~/.npmrc
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile

 


마무리

이번 작업을 통해

gitpackge 방식을 처음으로 접해보면서

버전 관리의 일관성, 자동 배포, 설치 속도 개선을 확보할 수 있었고,

개인적으로도 배포의 흐름 docker를 다루는 방식들을 엿볼 수 있어 재밌었습니다!

 

반응형