
솔직히 말해봅시다. 지난 연말, 여러분의 배포 파이프라인은 안녕하셨습니까? 2025년 한 해 동안 자바스크립트 생태계를 쑥대밭으로 만든 'Shai-Hulud' 공급망 공격 때문에, npm이 칼을 빼 들었습니다. 그 결과는 클래식 토큰(Classic Token)의 강제 폐기였고, 수많은 회사의 CI/CD가 멈춰 섰습니다.
실리콘밸리에서 15년을 구르며 뼈저리게 느낀 게 하나 있습니다. 플랫폼이 보안을 강화할 때마다, 엔지니어의 수명은 줄어듭니다. 보안은 필연적으로 '불편함(Friction)'을 동반하기 때문입니다.
하지만 불평만 하고 있을 순 없습니다. npm이 내놓은 새로운 생존 전략인 '단계적 게시(Staged Publishing)'와, 토큰 대란 이후 우리가 갖춰야 할 생존 루틴을 정리해 드립니다. 이대로만 세팅하면, 적어도 라이브러리 버전 하나 때문에 주말을 반납하는 일은 없을 겁니다.
1. 현황 분석: 왜 우리의 배포는 멈췄는가
npm은 그동안 '속도'에 미쳐있었습니다. npm publish 한 번이면 전 세계에 코드가 뿌려졌죠. 하지만 해커들은 그 속도를 이용해 악성코드를 퍼뜨렸습니다.
핵심 변경 사항
npm은 이제 '게시(Publish)'와 '공개(Release)'를 분리하려 합니다. 이것이 바로 단계적 게시(Staged Publishing)입니다. 패키지가 레지스트리에 올라가기 전, '검토 구간'을 두겠다는 겁니다.
문제는 이 과정에서 기존의 '클래식 토큰'을 없애버리고, OIDC 기반의 '신뢰된 게시(Trusted Publishing)'나 '세분화된 토큰(Granular Access Token)'으로 강제 이주를 시켰다는 점입니다. 이 과정이 매끄러웠냐고요? 천만에요.
현장에서 겪은 고통 (Pain Points)
- OIDC의 한계: 신규 패키지의 첫 배포(First Publish)에는 OIDC를 쓸 수 없습니다. 무조건 수동 설정이 필요합니다. 대규모 MSA 환경에서는 악몽 그 자체입니다.
- 세션 토큰의 짧은 수명: 초기에는 2시간마다 토큰이 만료되어, 사설 패키지 설치하다가 인증 에러가 뜨기 일쑤였습니다. (항의 끝에 12시간으로 늘어났지만, 여전히 불편합니다.)
- 문서와 현실의 괴리: CLI 업데이트는 늦었고, 에러 메시지는 불친절했습니다. 새벽에 "인증 실패" 로그만 띄우고 죽어버린 젠킨스(Jenkins)를 보며 욕을 삼킨 게 한두 번이 아닙니다.
2. 생존 전략: '죽지 않고' 배포하는 법
npm의 방향성은 명확합니다. "자동화된 편의성보다는 명시적인 승인을 우선하겠다." 우리는 이 흐름에 맞춰 파이프라인을 재설계해야 합니다.
[Step 1] OIDC '신뢰된 게시'로 전환하되, 맹신하지 말 것
GitHub Actions나 GitLab CI를 쓴다면, 장기(Long-lived) 시크릿을 없애는 OIDC 방식이 정답입니다. 하지만 앞서 말했듯 첫 배포 제약이 있습니다.
Action Item:
- 기존 패키지는 OIDC로 전면 교체하십시오. 토큰 로테이션의 고통에서 해방됩니다.
- 신규 패키지용 '부트스트랩' 절차를 만드십시오. 첫 배포는 로컬이나 별도의 어드민 파이프라인에서 수행하고, 이후 OIDC를 연결하는 스크립트를 짜야 합니다. 이걸 자동화하지 않으면 팀원들이 계속 당신을 부를 겁니다.
[Step 2] '단계적 게시'를 위한 승인 프로세스 내재화
npm이 도입할 Staged Publishing은 MFA(다중 요소 인증) 승인을 요구합니다. 즉, CI가 돌다가 사람의 승인을 기다리며 멈춘다는 뜻입니다. 이걸 멍하니 보고만 있으면 배포 속도가 반토막 납니다.
Action Item:
- ChatOps 도입: 슬랙(Slack)이나 팀즈 연동을 통해 "npm 배포 승인 대기 중" 알림을 받고, 버튼 하나로 MFA 승인이 되도록(혹은 링크로 바로 이동하도록) 워크플로를 짜야 합니다.
- 내부 검증 단계 추가: npm의 검토 기간을 우리도 활용해야 합니다. 스테이징(Staging)에 올라간 패키지를 내부 프로젝트에서
npm link나 프록시 레지스트리(Verdaccio 등)를 통해 스모크 테스트(Smoke Test)를 돌리십시오.
[Step 3] 보안 사고를 '탐지'의 영역으로 끌어들이기
ESLint 창시자 니콜라스 자카스(Nicholas C. Zakas)의 말처럼, 자격증명만 바꾼다고 해결될 문제가 아닙니다. 레지스트리 자체가 이상 징후를 탐지해야 합니다. 하지만 우리는 npm이 그걸 해주길 기다릴 수 없습니다.
Action Item:
- Socket.dev 같은 보안 툴을 CI 앞단에 붙이십시오. 배포 전에
install scripts유무, 평판 점수 등을 체크해서 위험하면 배포 자체를 막아야(Fail Fast) 합니다. - 장애 발생 시 "누가 토큰 흘렸어?"라며 범인 찾기(Blaming)를 멈추고, 시스템적으로 이상 징후를 모니터링할 수 있는 대시보드를 만드십시오.
- Socket.dev 같은 보안 툴을 CI 앞단에 붙이십시오. 배포 전에
3. 결론: 가용성보다 중요한 건 당신의 '퇴근'
보안이 강화될수록 개발자 경험(DX)은 필연적으로 나빠집니다. Adam Jones가 지적했듯, 수백 개의 패키지를 관리하는 팀에게 이번 변화는 재앙에 가까웠습니다.
하지만 기억하십시오. 시스템의 가용성(Availability) 99.999%를 지키려다 당신의 인생 가용성이 0%가 되어서는 안 됩니다.
npm의 변화는 귀찮지만, 공급망 공격으로 서비스가 털리는 것보다는 낫습니다.
지금 당장 팀의 CI 설정 파일을 열어보세요. 하드코딩된 토큰이 박혀 있다면, 그게 바로 당신의 주말을 앗아갈 시한폭탄입니다. OIDC로 바꾸고, 승인 절차를 다듬으세요.
기술 부채는 이자율이 매우 높습니다. 그리고 그 이자는 보통 새벽 3시에 청구됩니다.


