Skip to content

배포 가이드 ​

이 문서는 @lh-ui/vue3를 npm 공개 저장소에 게시하는 방법과, 개인 서버에 호스팅하는 두 가지 방식 (tarball 직접 링크와 registry 메타데이터)을 설명합니다.

게시는 수동과 CI 자동 듀얼 채널을 지원합니다: 로컬에서 changeset 명령을 실행하고 버전 번호와 변경 내역을 사람이 확인한 뒤 게시합니다 (아래 「게시 흐름」). main에 푸시할 때 .changeset/**에 변경이 있으면 GitHub Actions가 자동으로 version + publish를 실행합니다 (「GitHub Actions 자동 게시」 참고).

사전 준비 ​

1. npm 계정과 scope 소유권 ​

  • npm에 계정을 등록하고 2단계 인증(2FA)을 활성화합니다.

  • 계정이 @lh-ui scope에 대한 게시 권한을 가지고 있는지 확인합니다: scope는 선착순이며, 처음으로 @lh-ui/* 패키지를 게시한 계정이 해당 scope의 owner가 됩니다.

  • 로컬에서 로그인:

    bash
    npm whoami          # 현재 로그인된 계정 확인
    npm login           # 로그인하지 않은 경우 안내에 따라 로그인 + 2FA 진행

2. registry가 공개 저장소를 가리키는지 확인 ​

저장소 루트의 .npmrc에는 shamefully-hoist = true만 설정되어 있고 registry는 고정되어 있지 않아, 기본적으로 https://registry.npmjs.org/를 사용합니다. package.json의 publishConfig도 공개 저장소로 고정되어 있습니다:

json
"publishConfig": {
  "access": "public",
  "registry": "https://registry.npmjs.org/"
}

저장소 루트의 .npmrc에 개인 registry 주소를 적지 마세요 — 게시까지 개인 소스로 유도하게 됩니다. registry를 임시로 전환하려면 프로젝트 밖의 사용자 수준 ~/.npmrc나 명령줄 매개변수를 사용하세요.

3. 한 번의 게시에 포함되는 것 ​

files 허용 목록에는 빌드 결과물만 게시합니다: es/ (ESM + 타입 + 컴포넌트 스타일), lib/ (CJS), dist/ (UMD + 전체 스타일). 소스, 문서, 테스트, 스크립트는 모두 .npmignore로 제외됩니다. 게시 명령을 실행하면 prepublishOnly가 자동으로 pnpm build를 먼저 실행하므로, 수동으로 먼저 빌드할 필요가 없습니다.

게시 흐름 ​

1단계: changeset 작성 ​

사용자에게 보이는 모든 변경에는 changeset가 있어야 합니다. 이번 변경에 이미 작성했다면 2단계로 건너뜁니다.

bash
pnpm changeset

대화형 안내에 따라 @lh-ui/vue3, bump 유형 (major / minor / patch), 변경 내역을 선택합니다.

주의: 이 저장소의 changeset는 누적됩니다. 현재 .changeset/에는 수십 개의 소비되지 않은 changeset가 쌓여 있으며, 2단계의 changeset version을 실행하면 한 번에 모두 소비하여 동일한 버전 하나로 병합합니다. 나누어 게시하려면 git 브랜치나 changeset 파일 일부를 수동으로 옮기는 방식으로 진도를 조절해야 합니다.

2단계: 버전 번호 올리기, CHANGELOG 생성 ​

bash
pnpm changeset:version

이 명령은 다음 작업을 수행합니다:

  • changeset의 가장 높은 bump 수준에 따라 새 버전 번호를 계산하여 package.json에 기록
  • 모든 changeset를 취합하여 CHANGELOG.md 생성
  • 소비된 .changeset/*.md 삭제 (config.json의 commit: false로 인해 자동 커밋되지 않음)

실행 후 반드시 수동으로 확인:

bash
git status              # changeset가 소비되었는지, CHANGELOG가 생성되었는지 확인
git diff package.json   # 버전 번호가 예상과 일치하는지 확인

3단계: 게시 ​

bash
pnpm changeset:publish

내부적으로 pnpm publish를 실행하며, 흐름은 다음과 같습니다:

  1. prepublishOnly 트리거 → pnpm build (ESM / CJS / UMD / 타입 / 스타일 전체 빌드)
  2. publishConfig에 따라 패키징하여 npm 공개 저장소에 게시
  3. git tag 생성 및 푸시 (형식 @lh-ui/vue3@<version>)

publishConfig.access가 public이므로 scoped 패키지도 공개되며, --access public을 추가로 지정할 필요가 없습니다.

4단계: 푸시 (직접 실행) ​

bash
git push --follow-tags

게시 전 자체 점검 ​

정식 게시 전에 dry-run으로 실제 패키징 내용을 확인합니다:

bash
npm pack --dry-run

출력에 다음이 포함되어 있는지 확인:

  • es/, lib/, dist/ 세 디렉터리만 포함
  • src/, packages/, docs/, tests/, scripts/, ai/는 미포함
  • 크기가 합리적 (UMD 전체 패키지 약 600KB, 전체 스타일 약 700KB는 예상 범위 내)

게시 후 검증 ​

bash
# 1. npm에서 새 버전 확인
npm view @lh-ui/vue3
npm view @lh-ui/vue3 versions

# 2. 새 샌드박스 프로젝트에서 세 가지 모듈 형식 실측
pnpm create vite verify-pkg --template vue-ts
cd verify-pkg && pnpm add @lh-ui/vue3

샌드박스 프로젝트에서 항목별로 검증:

검증 항목작성법
전체 가져오기 (ESM)import LhUiPlus from '@lh-ui/vue3' + import '@lh-ui/vue3/dist/index.css'
필요별 컴포넌트 가져오기import { LhButton } from '@lh-ui/vue3'
필요별 스타일 가져오기 (sass 필요)import '@lh-ui/vue3/style/button'
필요별 스타일 가져오기 (sass 불필요)import '@lh-ui/vue3/style-css/button'
테마 도구import { getThemeVars } from '@lh-ui/vue3/theme'
CDN (수분 후 새로고침)https://unpkg.com/@lh-ui/vue3

개인 서버 호스팅(정적 tarball) ​

npm 공개 저장소가 주 게시 채널입니다. 자체 호스팅 미러가 필요하다면 (사내망 사용, npm 차단, 특정 버전 고정), tarball을 자신의 서버에 두는 것이 가장 가벼운 방안이며 개인 npm registry를 구축할 필요가 없습니다.

1. tarball 패키징 ​

bash
pnpm build
npm pack

생성되는 파일 이름은 lh-ui-vue3-<version>.tgz입니다 — npm이 scope의 @lh-ui/를 lh-ui-vue3-로 변환합니다 (슬래시가 하이픈으로). npm pack --dry-run으로 미리 확인할 수도 있습니다.

2. 서버에 업로드 ​

기존 nginx 사이트의 디렉터리 규칙을 따라 (문서 사이트는 /home/webuser/nginx/lh-ui/vue3/에 배포), 그 아래에 packages/ 디렉터리를 만들고 버전별로 디렉터리를 나누어 보관합니다:

/home/webuser/nginx/lh-ui/vue3/
├── index.html              # 문서 사이트
└── packages/
    ├── 1.0.0/
    │   └── lh-ui-vue3-1.0.0.tgz
    ├── 1.1.0/
    │   └── lh-ui-vue3-1.1.0.tgz
    └── latest              # 소프트링크, 현재 권장 버전을 가리킴
        └── lh-ui-vue3-1.1.0.tgz

대응하는 URL:

https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz

packages/는 정적 파일 디렉터리이므로 기존 사이트의 nginx 설정을 그대로 사용할 수 있고, location을 추가할 필요가 없습니다:

nginx
# 기존 문서 사이트 location이 /lhui/vue3/ 접두사를 이미 커버하며,
# packages/는 그 하위 디렉터리로 자동 접근 가능합니다.
# .tgz의 Content-Type으로 다운로드 가능하기만 하면 됩니다
# (nginx 기본 octet-stream으로 충분)
location /lhui/vue3/ {
    alias /home/webuser/nginx/lh-ui/vue3/;
    autoindex off;
}

3. 개인 서버에서 설치 ​

세 가지 동등한 작성법 중 하나를 선택:

bash
# pnpm
pnpm add https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz

# npm
npm install https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz

# yarn
yarn add https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz

또는 package.json에 직접 작성:

json
{
  "dependencies": {
    "@lh-ui/vue3": "https://www.lhgb.top/lhui/vue3/packages/1.0.0/lh-ui-vue3-1.0.0.tgz"
  }
}

4. 주의 사항 ​

  • registry 의존성 해석을 우회: tarball 설치는 registry를 조회하지 않고 의존성이 tarball 내의 선언에서 직접 옵니다. 이 패키지는 런타임 dependencies가 없고 peerDependencies.vue만 있으므로, 사용자 측 프로젝트에 Vue 3만 있으면 설치와 실행이 가능합니다.
  • 버전 메타데이터 없음: tarball 의존성에는 npm update가 작동하지 않으며, 업그레이드 시 URL을 수동으로 교체해야 합니다 (latest 소프트링크를 바꾼 뒤 재설치). 버전 고정 미러에는 적합하지만 잦은 업데이트에는 적합하지 않습니다.
  • https 필수: pnpm / npm / yarn은 기본적으로 http tarball 주소를 거부합니다.
  • pnpm-lock.yaml에는 전체 URL + integrity hash가 기록: 팀 협업 시 lockfile로 npm 접근 없이 설치를 정확히 재현할 수 있습니다.

개인 서버 호스팅(registry 메타데이터) ​

위의 tarball 직접 링크는 사용할 수 있지만 pnpm update가 작동하지 않고 lockfile에 URL 문자열이 남습니다. 사용자 측에서 일반 패키지처럼 pnpm add @lhgb/vue3로 설치하고 버전 해석과 dist-tags를 활용하고 싶다면, Nginx 정적 디렉터리에 npm registry 메타데이터를 추가로 구성하여 읽기 전용 registry로 작동시킬 수 있습니다. 두 방식은 공존 가능합니다.

1. 패키징 ​

bash
pnpm build
node scripts/pack-private.mjs

스크립트가 하는 일: 동일한 빌드 결과물의 이름을 @lhgb/vue3로 바꾸고 (name / publishConfig만 다름), npm pack으로 tarball을 생성하며, integrity(sha512)와 shasum(sha1)을 계산하고 registry 메타데이터 JSON을 조립하여 private-registry/에 출력합니다:

private-registry/
├── @lhgb/vue3              # 메타데이터 JSON (확장자 없음)
└── tarballs/@lhgb/vue3/
    └── lhgb-vue3-1.0.0.tgz

자주 쓰는 매개변수:

  • --dry-run: 생성될 파일 목록과 메타데이터만 출력하고 디스크에 기록하지 않습니다. 게시 전 확인용
  • --incremental: 기존 메타데이터를 읽어 새 버전을 병합하며, 과거 버전을 덮어쓰지 않습니다

2. 서버에 배포 ​

private-registry/의 내용을 서버 디렉터리에 업로드하고, scripts/nginx-private-registry.conf.example의 location을 적용합니다 (문서 사이트 /lhui/vue3/와 동일한 Nginx, 별도 location):

/home/webuser/nginx/registry/
├── @lhgb/vue3
└── tarballs/@lhgb/vue3/
    └── lhgb-vue3-1.0.0.tgz

Nginx 설정의 핵심은 default_type application/json입니다 — 메타데이터 파일에는 확장자가 없어서, 타입을 강제 선언하지 않으면 클라이언트가 일반 텍스트로 파싱에 실패합니다. 전체 설정은 scripts/nginx-private-registry.conf.example을 참고하세요 (.tgz는 최상위 정규 location에 단독으로 두어야 하며, ^~ /lhgb/ 안에 중첩하면 안 됩니다. 그렇지 않으면 접두사 일치가 정규 location을 건너뜁니다):

nginx
location ^~ /lhgb/ {
  alias /home/webuser/nginx/registry/;
  default_type application/json;
  autoindex off;
  expires 5m;
}

location ~ ^/lhgb/(.+\.tgz)$ {
  alias /home/webuser/nginx/registry/$1;
  default_type application/octet-stream;
  expires 1y;
  add_header Cache-Control "public, immutable" always;
}

3. 개인 registry에서 설치 ​

프로젝트 수준 또는 사용자 수준 .npmrc에 한 줄 추가:

ini
@lhgb:registry=https://www.lhgb.top/lhgb

세 가지 패키지 관리자 모두 동일:

bash
pnpm add @lhgb/vue3
# 또는
npm install @lhgb/vue3
# 또는
yarn add @lhgb/vue3

4. 공개 패키지와의 관계 ​

@lhgb/vue3와 @lh-ui/vue3는 동일 소스, 동일 버전이며 빌드 결과물도 완전히 같고 name과 registry만 다릅니다. 둘은 상호 교환 가능:

  • 사내망 / npm 차단 / 게시 소스 고정이 필요한 경우 @lhgb/vue3
  • 외부 공개, unpkg / jsdelivr CDN에 노출되기를 원하는 경우 @lh-ui/vue3

5. 주의 사항 ​

  • 메타데이터는 증분 업데이트: 게시할 때마다 --incremental로 새 버전을 병합하세요. 직접 덮어쓰면 과거 버전의 메타데이터를 잃어 이전 버전을 설치할 수 없게 됩니다.
  • tarball 이동 불가: 메타데이터의 tarball URL은 절대 경로이며, 파일 위치와 URL이 일대일로 대응해야 합니다.
  • 마찬가지로 https 필수: pnpm / npm / yarn은 기본적으로 http 주소를 거부합니다.
  • @lhgb registry를 저장소 루트 .npmrc에 쓰지 마세요: 루트 .npmrc에는 shamefully-hoist = true만 유지하고, 개인 registry 주소는 사용자 수준 ~/.npmrc에 작성하여 게시 흐름을 오염시키지 마세요.

GitHub Actions 자동 게시 ​

수동 흐름 외에 .github/workflows/release.yml이 자동 게시 채널을 제공합니다:

  • 트리거 조건: main에 푸시하며 .changeset/** 또는 package.json에 변경이 있는 경우, 또는 저장소 Actions 페이지에서 수동 트리거(workflow_dispatch).
  • 동작: pnpm build + pnpm verify:dts를 실행한 뒤 changesets/action의 version + publish를 실행합니다. 게시할 changeset가 없으면 아무것도 하지 않으므로 push에 연동해 두어도 안전합니다.
  • 필요한 secret: 저장소 Settings → Secrets and variables → Actions에서 NPM_TOKEN을 설정합니다 — npm에서 Granular Access Token을 생성하고 @lh-ui 조직의 publish 권한을 체크합니다.

수동과 자동 채널은 공존할 수 있습니다: 로컬 pnpm changeset:publish는 매 게시마다 사람이 확인해야 하는 경우에 적합하고, CI는 changeset가 준비되면 자동으로 눈덩이처럼 게시를 진행하는 경우에 적합합니다.

롤백 ​

bash
# 특정 버전을 더 이상 사용하지 않음으로 표시 (권장, 이미 설치한 사용자에게 영향 없음)
npm deprecate @lh-ui/vue3@1.0.0 "이 버전에는 xx 문제가 있으니 1.0.1로 업그레이드하세요"

# 완전히 게시 취소: 게시 후 72시간 이내이고 다른 패키지가 의존하지 않을 때만 가능
npm unpublish @lh-ui/vue3@1.0.0

CDN (unpkg / jsdelivr)의 캐시는 수 시간에서 하루 안에 만료되며, 롤백 후 샌드박스 프로젝트에서 버전이 지정된 URL로 이전 버전을 여전히 설치할 수 있는지 확인하세요.

국풍의 아름다움으로 코드의 토대를 세웁니다