npm trusted publishing 다중 설정 가이드: 토큰 없는 배포를 staging 중심으로 설계하기
요약: GitHub가 npm trusted publishing에 여러 OIDC 설정을 둘 수 있게 했습니다. AI 코딩 에이전트와 자동 릴리스가 늘어나는 상황에서 장기 npm 토큰을 줄이고, staging 승인과 malware scanning을 배포 파이프라인의 기본값으로 삼는 것이 중요해졌습니다.
왜 npm 배포 보안이 AI 시대에 더 중요해졌나
AI 코딩 에이전트가 릴리스 노트 작성, 버전 bump, PR 생성, 테스트 실행까지 맡기 시작했습니다. 여기까지는 좋습니다. 문제는 배포 권한입니다. 자동화가 편해질수록 장기 토큰이 CI 환경에 남기 쉽고, 한 번 탈취되면 패키지 공급망 전체가 위험해집니다.
npm 패키지는 많은 서비스의 transitive dependency로 들어갑니다. 작은 패키지 하나가 오염되어도 실제 영향 범위는 큽니다. 그래서 배포 보안은 이제 대형 오픈소스만의 문제가 아닙니다. 사내 패키지, 디자인 시스템, CLI 도구, SDK를 운영하는 팀도 같은 기준을 가져야 합니다.
GitHub changelog에 따르면 npm trusted publishing은 이제 패키지당 여러 trusted publishing, 즉 OIDC 구성을 지원합니다. stable, prerelease, staging 등 workflow를 나누려던 팀이 더 이상 장기 토큰이나 우회 workflow에 기대지 않아도 됩니다.
trusted publishing의 실무 의미
trusted publishing은 CI가 npm 장기 토큰을 들고 있는 대신, GitHub Actions 같은 신뢰된 실행 환경의 OIDC 토큰을 npm이 검증해 배포를 허용하는 방식입니다. 즉 “이 workflow가 이 repo의 이 환경에서 실행됐다”는 사실을 바탕으로 권한을 부여합니다.
장점은 명확합니다.
- CI secret에 장기 npm token을 저장하지 않아도 됩니다.
- repo, workflow, environment 조건으로 배포 경로를 제한할 수 있습니다.
- 토큰 회전 누락 위험이 줄어듭니다.
- 어떤 workflow가 배포했는지 추적하기 쉽습니다.
이번 업데이트의 핵심은 패키지 하나에 여러 구성을 둘 수 있다는 점입니다. 예전에는 한 패키지가 하나의 OIDC 설정에 묶이면서 stable과 prerelease를 나누기가 애매했습니다. 이제 각 구성은 독립적이고 additive하게 동작합니다. incoming OIDC token이 어느 한 구성과 맞으면 publish 또는 stage가 허용됩니다.
staging-only를 기본값으로 삼아야 하는 이유
GitHub는 모든 trusted publishing configuration이 기본적으로 stage를 할 수 있고, direct publishing은 opt-in이라고 설명합니다. 또한 staged publishing을 권장합니다. 이유는 간단합니다. compromised workflow가 바로 registry에 패키지를 올리는 것을 막기 위해서입니다.
실무에서는 direct publish가 편해 보입니다. main에 merge되면 version bump 후 바로 publish되는 구조는 빠릅니다. 하지만 AI 에이전트가 PR을 만들고, 자동 merge bot이 붙고, 릴리스 workflow가 복잡해질수록 실수의 전파 속도도 빨라집니다. staging을 두면 최소 한 번 사람이 릴리스 산출물을 확인할 수 있습니다.
특히 이번 업데이트에서는 staged publishing queue에서 malware scanning이 완료되기 전까지 approval button이 비활성화됩니다. 패키지가 사용 가능해지기 전에 스캔이 먼저 끝나야 합니다. 이건 배포 파이프라인에 “사람 승인 + 자동 스캔”이라는 두 개의 관문을 넣는 효과가 있습니다.
추천 구성: stable, prerelease, emergency를 나눈다
다중 trusted publishing을 쓸 때 아무렇게나 늘리면 오히려 복잡해집니다. 보통은 세 가지 경로로 충분합니다.
첫째, stable release입니다. main branch 또는 release branch에서만 stage할 수 있게 합니다. environment는 npm-production처럼 분리하고, direct publish는 끕니다. approval은 패키지 메인테이너 또는 release manager가 합니다.
둘째, prerelease입니다. beta, canary, next 태그를 다루는 workflow입니다. 이 경로도 stage를 기본으로 두되, 내부 패키지나 낮은 위험 패키지는 direct publish를 제한적으로 검토할 수 있습니다. 그래도 공개 패키지라면 stage가 안전합니다.
셋째, emergency patch입니다. 보안 패치를 빠르게 내야 할 때 쓰는 별도 workflow입니다. 조건은 더 좁게 잡아야 합니다. 특정 branch, 특정 environment, 수동 workflow_dispatch, 두 명 이상의 승인 같은 형태가 좋습니다. emergency라는 이름을 붙였다고 권한을 넓히면 안 됩니다.
AI 에이전트가 릴리스에 참여할 때의 권한 설계
AI 코딩 에이전트가 버전 업데이트나 changelog 초안을 만들 수는 있습니다. 하지만 publish 권한을 직접 주는 건 별도 문제입니다. 권장 역할 분리는 다음과 같습니다.
- AI 에이전트: 변경 후보 생성, 테스트 실행, changelog 초안 작성
- CI: 빌드, 테스트, provenance 생성, staged package 업로드
- 사람: staged package 확인, approval, rollback 판단
- registry: OIDC 검증, malware scanning, publish 기록 저장
이 구조에서는 AI가 틀려도 바로 registry에 반영되지 않습니다. 에이전트가 package.json 버전을 잘못 올리거나, generated file을 빠뜨리거나, breaking change를 minor로 적어도 staging 단계에서 잡을 수 있습니다.
운영 체크 포인트
trusted publishing을 켰다고 끝이 아닙니다. 운영에서는 아래 항목을 주기적으로 봐야 합니다.
- 패키지별 trusted publishing configuration 목록
- direct publishing이 켜진 configuration 여부
- staging 승인자 권한
- GitHub Actions workflow 파일 변경 이력
- environment protection rule
- release branch 보호 규칙
- npm versions tab의 staged, approved, rejected 기록
특히 configurations never restrict one another라는 설명을 기억해야 합니다. 여러 설정은 서로를 제한하지 않습니다. 하나라도 매칭되면 허용됩니다. 따라서 느슨한 설정 하나가 전체 보안을 약화시킬 수 있습니다.
마무리 체크리스트
- npm 장기 토큰을 CI secret에서 제거할 계획을 세웁니다.
- 패키지당 stable, prerelease, emergency OIDC 구성을 분리합니다.
- 기본은 staging-only로 두고 direct publish는 예외로만 허용합니다.
- staged approval 전에 malware scanning이 끝나는지 확인합니다.
- AI 에이전트에는 publish 권한을 주지 말고 PR과 changelog 생성까지만 맡깁니다.
- workflow 파일과 environment rule 변경은 코드 리뷰 필수로 둡니다.
- npm versions tab에서 승인·거절·staged 기록을 주기적으로 확인합니다.
npm trusted publishing 다중 설정은 편의 기능이 아니라 공급망 보안 기능입니다. AI 자동화가 배포 파이프라인까지 들어오는 팀일수록 토큰 없는 배포, staging 승인, 스캔 완료 후 승인이라는 기본기를 먼저 잡아야 합니다.