배포 가이드
이 문서는 @lh-ui/vue3를 npm 공개 저장소에 게시하는 방법과, 개인 서버에 호스팅하는 두 가지 방식 (tarball 직접 링크와 registry 메타데이터)을 설명합니다.
게시는 수동과 CI 자동 듀얼 채널을 지원합니다: 로컬에서 changeset 명령을 실행하고 버전 번호와 변경 내역을 사람이 확인한 뒤 게시합니다 (아래 「게시 흐름」). main에 푸시할 때 .changeset/**에 변경이 있으면 GitHub Actions가 자동으로 version + publish를 실행합니다 (「GitHub Actions 자동 게시」 참고).
사전 준비
1. npm 계정과 scope 소유권
npm에 계정을 등록하고 2단계 인증(2FA)을 활성화합니다.
계정이
@lh-uiscope에 대한 게시 권한을 가지고 있는지 확인합니다: scope는 선착순이며, 처음으로@lh-ui/*패키지를 게시한 계정이 해당 scope의 owner가 됩니다.로컬에서 로그인:
bashnpm whoami # 현재 로그인된 계정 확인 npm login # 로그인하지 않은 경우 안내에 따라 로그인 + 2FA 진행
2. registry가 공개 저장소를 가리키는지 확인
저장소 루트의 .npmrc에는 shamefully-hoist = true만 설정되어 있고 registry는 고정되어 있지 않아, 기본적으로 https://registry.npmjs.org/를 사용합니다. package.json의 publishConfig도 공개 저장소로 고정되어 있습니다:
"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단계로 건너뜁니다.
pnpm changeset대화형 안내에 따라 @lh-ui/vue3, bump 유형 (major / minor / patch), 변경 내역을 선택합니다.
주의: 이 저장소의 changeset는 누적됩니다. 현재
.changeset/에는 수십 개의 소비되지 않은 changeset가 쌓여 있으며, 2단계의changeset version을 실행하면 한 번에 모두 소비하여 동일한 버전 하나로 병합합니다. 나누어 게시하려면 git 브랜치나 changeset 파일 일부를 수동으로 옮기는 방식으로 진도를 조절해야 합니다.
2단계: 버전 번호 올리기, CHANGELOG 생성
pnpm changeset:version이 명령은 다음 작업을 수행합니다:
- changeset의 가장 높은 bump 수준에 따라 새 버전 번호를 계산하여
package.json에 기록 - 모든 changeset를 취합하여
CHANGELOG.md생성 - 소비된
.changeset/*.md삭제 (config.json의commit: false로 인해 자동 커밋되지 않음)
실행 후 반드시 수동으로 확인:
git status # changeset가 소비되었는지, CHANGELOG가 생성되었는지 확인
git diff package.json # 버전 번호가 예상과 일치하는지 확인3단계: 게시
pnpm changeset:publish내부적으로 pnpm publish를 실행하며, 흐름은 다음과 같습니다:
prepublishOnly트리거 →pnpm build(ESM / CJS / UMD / 타입 / 스타일 전체 빌드)publishConfig에 따라 패키징하여 npm 공개 저장소에 게시- git tag 생성 및 푸시 (형식
@lh-ui/vue3@<version>)
publishConfig.access가 public이므로 scoped 패키지도 공개되며, --access public을 추가로 지정할 필요가 없습니다.
4단계: 푸시 (직접 실행)
git push --follow-tags게시 전 자체 점검
정식 게시 전에 dry-run으로 실제 패키징 내용을 확인합니다:
npm pack --dry-run출력에 다음이 포함되어 있는지 확인:
es/,lib/,dist/세 디렉터리만 포함src/,packages/,docs/,tests/,scripts/,ai/는 미포함- 크기가 합리적 (UMD 전체 패키지 약 600KB, 전체 스타일 약 700KB는 예상 범위 내)
게시 후 검증
# 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 패키징
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.tgzpackages/는 정적 파일 디렉터리이므로 기존 사이트의 nginx 설정을 그대로 사용할 수 있고, location을 추가할 필요가 없습니다:
# 기존 문서 사이트 location이 /lhui/vue3/ 접두사를 이미 커버하며,
# packages/는 그 하위 디렉터리로 자동 접근 가능합니다.
# .tgz의 Content-Type으로 다운로드 가능하기만 하면 됩니다
# (nginx 기본 octet-stream으로 충분)
location /lhui/vue3/ {
alias /home/webuser/nginx/lh-ui/vue3/;
autoindex off;
}3. 개인 서버에서 설치
세 가지 동등한 작성법 중 하나를 선택:
# 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에 직접 작성:
{
"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. 패키징
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.tgzNginx 설정의 핵심은 default_type application/json입니다 — 메타데이터 파일에는 확장자가 없어서, 타입을 강제 선언하지 않으면 클라이언트가 일반 텍스트로 파싱에 실패합니다. 전체 설정은 scripts/nginx-private-registry.conf.example을 참고하세요 (.tgz는 최상위 정규 location에 단독으로 두어야 하며, ^~ /lhgb/ 안에 중첩하면 안 됩니다. 그렇지 않으면 접두사 일치가 정규 location을 건너뜁니다):
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에 한 줄 추가:
@lhgb:registry=https://www.lhgb.top/lhgb세 가지 패키지 관리자 모두 동일:
pnpm add @lhgb/vue3
# 또는
npm install @lhgb/vue3
# 또는
yarn add @lhgb/vue34. 공개 패키지와의 관계
@lhgb/vue3와 @lh-ui/vue3는 동일 소스, 동일 버전이며 빌드 결과물도 완전히 같고 name과 registry만 다릅니다. 둘은 상호 교환 가능:
- 사내망 / npm 차단 / 게시 소스 고정이 필요한 경우
@lhgb/vue3 - 외부 공개, unpkg / jsdelivr CDN에 노출되기를 원하는 경우
@lh-ui/vue3
5. 주의 사항
- 메타데이터는 증분 업데이트: 게시할 때마다
--incremental로 새 버전을 병합하세요. 직접 덮어쓰면 과거 버전의 메타데이터를 잃어 이전 버전을 설치할 수 없게 됩니다. - tarball 이동 불가: 메타데이터의
tarballURL은 절대 경로이며, 파일 위치와 URL이 일대일로 대응해야 합니다. - 마찬가지로 https 필수: pnpm / npm / yarn은 기본적으로 http 주소를 거부합니다.
@lhgbregistry를 저장소 루트.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가 준비되면 자동으로 눈덩이처럼 게시를 진행하는 경우에 적합합니다.
롤백
# 특정 버전을 더 이상 사용하지 않음으로 표시 (권장, 이미 설치한 사용자에게 영향 없음)
npm deprecate @lh-ui/vue3@1.0.0 "이 버전에는 xx 문제가 있으니 1.0.1로 업그레이드하세요"
# 완전히 게시 취소: 게시 후 72시간 이내이고 다른 패키지가 의존하지 않을 때만 가능
npm unpublish @lh-ui/vue3@1.0.0CDN (unpkg / jsdelivr)의 캐시는 수 시간에서 하루 안에 만료되며, 롤백 후 샌드박스 프로젝트에서 버전이 지정된 URL로 이전 버전을 여전히 설치할 수 있는지 확인하세요.