
npm 배포 토큰을 지워도 된다…OIDC 전환은 검증 후 폐기가 순서다

GitHub Actions에서 장기 npm 쓰기 토큰 없이 패키지를 발행하려면 Trusted Publisher를 등록하고, 발행 작업에 OIDC 권한을 준 뒤 토큰을 전달하지 않은 상태로 새 버전을 실제 배포해야 한다. npm의 Trusted Publishing 지침은 npm CLI 11.5.1 이상, Node.js 22.14.0 이상과 GitHub Actions 작업의 id-token: write 권한을 요구하며, 기존 토큰은 전환을 검증한 다음 차단하고 폐기하도록 안내한다. 설정 화면에서 연결을 저장한 것만으로는 발행 경로가 작동하는지 알 수 없다.
첫 검증 배포에서는 발행 단계에 기존 쓰기 토큰을 전달하지 않아야 성공한 인증 경로를 구분할 수 있다. GitHub의 OIDC 설명에 따르면 작업마다 고유한 토큰이 발급되고, 상대 서비스가 그 토큰의 클레임을 확인한 뒤 작업 수명에 한정된 자격 증명을 제공한다. npm은 신뢰하도록 등록된 워크플로에서 이 방식으로 발행 요청을 인증한다.
실행 환경부터 배포 명령까지 맞춘다
워크플로에서 Node.js 버전만 지정했다면 발행 작업이 실제로 사용하는 npm 버전도 확인한다. 개발자의 로컬 환경에서 새 CLI가 실행되더라도 GitHub Actions의 러너에는 다른 버전이 들어 있을 수 있다. 버전 확인 명령을 발행 작업에 두고 요구 조건보다 낮다면 CLI를 올린 다음 같은 작업에서 다시 확인하는 편이 정확하다.
npm으로 발행하는 작업은 GitHub 호스팅 러너에서 실행해야 한다. 자체 호스팅 러너에서 릴리스하던 프로젝트라면 빌드와 테스트를 어떻게 나눌지 결정하되, Trusted Publishing으로 발행하는 작업은 지원되는 러너로 옮겨야 한다. 러너 조건을 바꾸지 않은 채 npm 쪽 연결만 추가하면 발행 단계에서 인증 문제가 드러난다.
직접 공개하는 npm publish와 검토 단계를 거치는 npm stage publish 중 어느 명령을 쓸지도 정한다. 새 Trusted Publisher 연결은 단계적 발행을 허용하며, 직접 발행하려면 Allowed actions에서 npm publish도 허용해야 한다. 워크플로의 명령과 npm 설정의 허용 작업이 다르면 저장소와 OIDC 권한이 올바르더라도 의도한 방식으로 발행할 수 없다.
패키지 설정에 정확한 워크플로를 등록한다
npmjs.com의 해당 패키지 설정에서 Trusted Publisher로 GitHub Actions를 선택한다. Organization or user에는 저장소 소유자, Repository에는 저장소 이름을 넣는다. Workflow filename에는 .github/workflows/ 전체 경로가 아닌 파일 이름과 확장자만 입력한다. 예를 들어 파일 경로가 .github/workflows/publish.yml이라면 입력할 값은 publish.yml이다.
GitHub Environment를 배포 승인에 사용한다면 Environment name도 입력하고 실제 발행 작업의 environment 값과 맞춘다. 각 이름의 철자와 대소문자를 그대로 대조해야 한다. npm은 Trusted Publisher를 저장하는 순간 워크플로 구성을 검증하지 않으므로, 오타는 발행을 시도할 때 인증 오류로 나타난다.
package.json의 repository.url이 실제 발행 저장소를 가리키는지도 확인한다. 포크하거나 소유자를 옮긴 패키지는 이 값에 이전 저장소가 남아 있을 수 있다. 연결에 잘못된 필드를 입력했다면 기존 Trusted Publisher를 편집하는 대신 삭제하고 올바른 값으로 다시 등록해야 한다.
발행 작업에 OIDC 권한을 주고 쓰기 토큰을 뺀다
배포 워크플로의 발행 작업에 permissions의 id-token: write를 지정하고, 소스를 체크아웃한다면 contents: read도 함께 둔다. id-token: write는 npm 레지스트리에 대한 일반 쓰기 권한이 아니라 GitHub가 작업의 OIDC 토큰을 발급할 수 있도록 하는 권한이다. 권한을 워크플로 전체에 둘 수도 있지만 발행 작업에 지정하면 어느 작업이 토큰을 요청할 수 있는지 분명해진다.
작업에서는 소스를 체크아웃하고 actions/setup-node로 지원되는 Node.js를 설정한 뒤 registry-url을 https://registry.npmjs.org로 지정한다. 이어 의존성을 설치하고 필요한 빌드와 테스트를 실행한 다음 npm publish를 호출한다. 현재 릴리스 작업이 다른 레지스트리로 발행하도록 설정돼 있다면 이 값을 먼저 바로잡아야 npm의 Trusted Publisher 연결을 검증할 수 있다.
검증 배포의 npm publish 단계에는 NODE_AUTH_TOKEN으로 기존 쓰기 토큰을 전달하지 않는다. 작업 전체의 env, 저장소의 .npmrc, 발행 스크립트에도 토큰 참조가 남아 있는지 살핀다. npm CLI는 OIDC 인증을 먼저 시도한 뒤 기존 토큰 인증으로 돌아갈 수 있으므로, 쓰기 토큰을 건네준 채 성공한 배포만으로는 OIDC 전환을 입증하기 어렵다. GitHub Secret에 보관된 기존 토큰은 검증이 끝날 때까지 유지하되 발행 작업에서 참조하지 않도록 한다.
재사용 워크플로를 호출하는 구조에서는 npm publish 명령이 들어 있는 파일과 호출하는 파일을 함께 확인한다. npm의 인증 검사는 호출하는 워크플로의 이름을 기준으로 할 수 있으며, 이 경우 부모와 자식 워크플로 모두 id-token: write 권한이 필요하다. 등록한 파일 이름과 실제 인증에 사용되는 워크플로가 다른 경우에는 단순히 발행 명령이 있는 파일 이름으로 설정을 바꿔도 해결되지 않는다.
비공개 의존성은 설치 단계에 읽기 권한을 준다
Trusted Publishing은 패키지를 발행할 때의 인증을 처리한다. 비공개 npm 패키지가 의존성에 있다면 npm ci에는 별도의 읽기 권한이 필요하다. 기존 쓰기 토큰을 계속 전달하는 대신 해당 의존성을 읽을 수 있는 세분화된 읽기 전용 토큰을 GitHub Secret에 저장하고, npm ci 단계의 NODE_AUTH_TOKEN으로만 제공한다. npm publish 단계에는 그 값도 전달하지 않는다.
설치 단계에서 인증 오류가 났다면 비공개 의존성에 대한 읽기 권한과 토큰이 전달되는 단계를 확인한다. 설치는 통과했지만 npm publish가 인증에 실패했다면 Trusted Publisher의 저장소·워크플로 값, 발행 작업의 OIDC 권한, 러너와 CLI 버전을 살펴본다. 두 단계에 필요한 자격 증명이 다르므로, 비공개 의존성이 있어도 장기 쓰기 토큰 없이 발행할 수 있다.
새 버전과 provenance로 첫 배포를 검증한다
설정을 저장한 뒤에는 실제 릴리스에 사용할 새 패키지 버전을 준비하고 평소의 태그 또는 수동 실행 경로로 배포 작업을 돌린다. 설치·빌드·테스트가 통과했는지 확인한 다음 npm publish 단계가 토큰 없이 실행돼 성공했는지 본다. 이어 npm 레지스트리에 그 버전이 등록됐는지 확인한다. 워크플로 전체가 성공으로 표시돼도 조건문 때문에 발행 명령이 건너뛰어졌다면 인증 경로는 아직 검증되지 않았다.
공개 GitHub 저장소에서 공개 npm 패키지를 Trusted Publishing으로 발행하면 provenance 증명이 자동 생성되므로 별도의 --provenance 옵션이 필요하지 않다. npm의 provenance 안내는 증명이 패키지의 소스와 빌드 정보에 연결되며, 설치한 패키지의 증명을 npm audit signatures로 검증할 수 있다고 설명한다. 패키지 페이지의 provenance 표시도 발행된 버전과 함께 살펴볼 수 있다.
저장소가 비공개라면 패키지를 공개로 발행하더라도 provenance는 생성되지 않는다. 이때 증명 표시가 없다는 이유만으로 OIDC 발행이 실패했다고 판단해서는 안 된다. 공개 저장소와 공개 패키지 조건을 충족하는데 증명이 없다면 provenance를 끄는 설정이 있는지 확인한다. 증명은 발행 출처를 확인하는 수단이지 패키지 코드의 안전성을 보증하는 표시는 아니다.
npm whoami의 결과도 OIDC 전환의 합격 기준은 아니다. 이 명령은 발행 작업 중에 일어나는 OIDC 인증 상태를 보여주지 않는다. npm publish에서 인증 오류가 발생했다면 워크플로 파일명의 확장자와 대소문자, 저장소 소유자, package.json의 repository.url을 먼저 비교하고 id-token: write 권한이 실제 발행 작업에 적용됐는지 확인한다.
검증이 끝나면 기존 토큰의 발행 권한을 닫는다
토큰이 전달되지 않은 작업에서 새 버전의 발행을 확인한 다음, 해당 패키지의 Settings → Publishing access에서 Require two-factor authentication and disallow tokens를 선택하고 저장한다. 이 설정은 전통적인 토큰을 이용한 발행을 막으며 Trusted Publisher의 OIDC 발행은 허용한다. 연결을 저장하자마자 제한을 켜면 설정 오류가 있는 상태에서 다음 릴리스 경로가 막힐 수 있으므로 실제 배포 결과를 먼저 확인하는 순서가 안전하다.
그다음 사용하지 않는 자동화 쓰기 토큰을 npm에서 폐기하고 GitHub Actions Secret과 워크플로의 참조를 제거한다. 같은 토큰으로 다른 패키지도 발행하고 있었다면 그 사용처의 전환이나 권한 분리를 먼저 마쳐야 한다. 비공개 의존성 설치에 쓰는 읽기 전용 토큰은 발행 토큰과 목적이 다르므로, 필요한 설치 단계에만 남겨 둔다.
함께 읽기:
관련 기사
뉴스레터 구독
최신 Web3, AI, 암호화폐 뉴스를 이메일로 받아보세요.




