jpm

빠르고 작으며 기본적으로 안전한 JavaScript 패키지 매니저

curl -fsSL https://getjpm.sh | sh

모든 코드는 Claude Code가 작성했습니다. 엔지니어 한 명이 이끌었습니다. 다른 모든 프로젝트의 테스트로 검증했습니다.

  • ~2 MB바이너리 하나, 설치할 런타임 없음
  • 1.22 sGitHub CI에서 nuxt 콜드 설치
  • 34 MBGitHub CI에서 nuxt 설치에 쓰는 메모리

속도

CI가 시간을 쓰는 곳에서 빠르게

실제 프로젝트 3개, 설치 단계 4가지, 패키지 매니저 8개를 실제 npm 레지스트리에서 측정했습니다. GitHub CI에서 jpm은 12개 칸 중 9개에서 가장 빠르며, 나머지 3개도 측정한 그대로 보여 줍니다.

머신
단계
프로젝트

캐시 없음, 락파일 없음, node_modules 없음.

설치 경과 시간, 짧을수록 빠름GitHub CI, Linux · nuxt · 패키지 591개
GitHub CI, Linux, 콜드, nuxt · 패키지 591개
패키지 매니저경과 시간
jpm1.22 s
bun 1.4.21.28 s
pnpm 12.8.11.72 s
aube 2.6.03.00 s
upm 1.3.13.52 s
deno 2.9.67.64 s
yarn 4.18.19.63 s
npm 12.1.018.54 s

여기서는 jpm이 가장 빠르며, npm보다 15× 빠릅니다.

실제 경과 시간 중앙값: 4코어 ubuntu-latest(5회 실행), Defender를 켠 Windows 11(3회 실행), 2026-09-30. CPU 시간을 포함한 전체 표는 docs/benchmarks.md에 있습니다.

시작하기

명령 하나로 전환

프로젝트에서 jpm install을 실행하세요. jpm은 지금 쓰는 락파일을 같은 버전 그대로 자체 jpm.lock으로 가져옵니다.

  • package-lock.json과 npm-shrinkwrap.json(npm 7+), pnpm-lock.yaml(pnpm 9+), bun.lock은 그대로 옮겨집니다. 버전도 트리도 같고, 레지스트리 조회도 없습니다.
  • yarn 1이든 yarn 2 이상이든 yarn.lock에서 yarn이 고른 버전은 모두 유지됩니다. jpm은 yarn.lock에 기록되지 않은 정보(peer, 플랫폼, bin)만 레지스트리에 요청합니다.
  • 기존 락파일은 건드리지 않습니다. 준비되면 삭제하세요.
  • 전환하는 동안에도 CI는 계속 동작합니다. jpm.lock을 커밋하기 전까지 jpm ci와 jpm install --frozen-lockfile은 기존 락파일 그대로 설치합니다.
  • 워크스페이스, pnpm-workspace.yaml, 카탈로그, 오버라이드와 resolutions, 패치도 읽습니다.

이전 형식, 최신이 아닌 락파일 등 자세한 내용: docs/migrating.md.

$ cd your-project
$ jpm install   # package-lock.json / pnpm-lock.yaml / yarn.lock / bun.lock 읽기 → jpm.lock 작성

경량

있는 줄도 모를 만큼 작게

뒤에 아무것도 필요 없는 바이너리 하나, 메모리를 적게 쓰는 설치, 그리고 각 파일을 한 번만 저장하는 스토어.

모든 수치가 jpm에 유리한 것은 아닙니다. npm과 yarn은 압축된 tarball을 보관하므로 캐시가 더 작습니다. jpm은 파일을 압축 해제한 상태로 보관해 바로 링크할 수 있게 합니다.

GitHub CI, Linux, 2026-09-30. 바이너리 크기는 README에 적힌 어림값입니다.

바이너리 크기(대략)
바이너리 크기(대략)
jpm~2 MB
pnpm~60 MB
bun~80 MB
aube~150 MB
최대 메모리, nuxt ci 설치
최대 메모리, nuxt ci 설치
jpm34 MB
bun89 MB
pnpm184 MB
npm387 MB
nuxt 콜드 설치 후 디스크 사용량(node_modules와 스토어)
nuxt 콜드 설치 후 디스크 사용량(node_modules와 스토어)
jpm244 MB
bun261 MB
pnpm290 MB
npm443 MB
next 콜드 설치 후 CI 캐시
next 콜드 설치 후 CI 캐시
npm194 MB
yarn328 MB
jpm347 MB
pnpm433 MB
bun466 MB

스토리지

파일은 한 번만 저장. 패키지는 한 번만 빌드.

jpm은 머신마다 스토어 하나를 두고, 각 패키지의 디렉터리를 한 번만 빌드해 그 패키지를 쓰는 모든 프로젝트가 함께 씁니다. 다시 설치할 때는 대부분 링크만 만들면 됩니다.

  1. 콘텐츠 주소 기반 스토어

    각 tarball은 무결성을 검증한 뒤 ~/.jpm/store에 한 번만 압축 해제됩니다. 모든 파일은 해시 기준으로 한 번만, 읽기 전용으로 보관됩니다.

  2. 전역 가상 스토어

    각 패키지는 하나의 항목으로 한 번만 빌드됩니다. 항목은 name@version이며, 의존성이 있으면 의존성 그래프의 짧은 다이제스트가 붙습니다. 파일은 스토어에서 하드링크되고 의존성은 그 옆에 링크되므로, 선언한 것만 import할 수 있습니다.

  3. 여러분의 node_modules

    프로젝트의 node_modules는 이 항목들에 링크됩니다. 웜 설치는 이 몇 개의 링크만 만듭니다. GitHub CI에서 nitro 기준 4 ms입니다.

  4. 다른 모든 프로젝트

    같은 머신의 다음 프로젝트도 같은 항목에 링크됩니다. 아무것도 바뀌지 않았다면 반복 설치는 링크 몇 개만 확인하고 1–2 ms 만에 끝납니다.

~/.jpm/store파일, 해시 기준3fa19c07e4b271d80b5ec6a3하드링크~/.jpm/store/v1/links항목, 한 번만 빌드[email protected]node_modules/debugnode_modules/ms[email protected]node_modules/msapp-one/app-two/node_modules/debugnode_modules/debug링크

Next.js와 Nuxt: 프로젝트 안에

Next의 Turbopack은 프로젝트 밖의 코드를 컴파일하지 않고, Nuxt는 선언하지 않은 패키지를 import합니다. 그래서 next나 nuxt에 의존하는 프로젝트에서는 jpm이 대신 node_modules/.jpm에 항목을 빌드하며, 여전히 스토어에서 하드링크합니다.

node_modules/next -> .jpm/[email protected]…/node_modules/next
node_modules/.jpm/[email protected]…/node_modules/next/
node_modules/.jpm/[email protected]/node_modules/react/

전체 내용: docs/how-it-works.md.

보안

기본적으로 안전

안전한 설정은 따로 요청하지 않아도 기본으로 적용됩니다. 완화할지는 패키지나 클론한 저장소가 아니라, 여러분이 자신의 설정에서 결정합니다.

  • 설치 스크립트는 승인을 기다립니다

    대부분의 npm 악성 코드가 실행되는 경로인 의존성의 설치 스크립트는, 해당 패키지와 버전을 jpm approve하기 전까지 실행되지 않습니다. 새 버전은 다시 승인을 기다립니다.

  • 새 버전은 하루를 기다립니다

    최근 하루 안에 게시된 버전은 선택되지 않습니다(min-release-age). 트리 깊숙한 패키지가 그 버전을 정확히 고정해도 마찬가지이므로, 탈취된 릴리스가 고정 버전을 타고 들어올 수 없습니다.

  • 뜻밖의 출처 없음

    게시된 패키지는 git이나 tarball 의존성, 또는 자기 밖의 경로를 끌어올 수 없습니다. 코드의 출처는 여러분의 프로젝트와 그 워크스페이스만 정할 수 있습니다.

  • 보이기 전에 검증

    모든 패키지는 파일이 프로젝트에 보이기 전에 락파일의 무결성 값과 대조해 검증됩니다.

  • 락파일에 비밀 정보 없음

    자격 증명은 절대 jpm.lock에 기록되지 않습니다. 토큰은 .npmrc에 남고, 비밀번호가 포함된 git url은 거부됩니다.

  • 클론한 저장소가 기준을 낮출 수 없습니다

    프로젝트 자체의 .npmrc로는 TLS 검사를 끄거나, CA나 프록시를 바꾸거나, 릴리스 대기 기간을 완화할 수 없습니다. jpm은 그곳의 해당 설정을 무시하고 경고로 알려 줍니다.

  • 자체 TLS, OpenSSL 없음

    jpm은 자체 코드로 TLS를 처리하며, Project Wycheproof와 RFC 테스트 벡터로 검증했습니다. 인증서는 Mozilla의 루트와 시스템 루트를 기준으로 확인합니다.

  • 런타임은 서명으로 검증

    패키지가 요청한 Node.js 런타임은 해당 릴리스의 SHASUMS256.txt와 대조하며, 그 서명이 Node의 릴리스 키와 일치할 때만 신뢰합니다.

  • 공격할 곳이 적습니다

    ~2 MB 바이너리 하나로, 설치할 런타임도 자체 의존성 트리도 없습니다. 여러분과 레지스트리 사이의 코드가 그만큼 적습니다.

기본적으로 안전하다고 해서 샌드박스는 아닙니다. 승인한 스크립트는 여러분의 권한으로 실행됩니다. 자세한 내용: docs/install-scripts.md, docs/configuration.md.

이야기

Claude Code가 작성하고, 다른 모든 프로젝트의 테스트로 검증했습니다.

시작은 Syntax 팟캐스트의 한 에피소드였습니다. upm이 다른 도구보다 빠르고 작다고 소개했죠. 작은 이유는 Node.js 위에서 돌기 때문입니다. 그렇다면 Rust로 포팅해서 정말로 작게 만들면 어떨까? 그리고 AI가 한 번에 만든 결과물을 CI에서 믿고 쓸 만한 것으로 바꾸려면 무엇이 필요할까?

Claude Opus 5.5로 동작하는 Claude Code가 자체 TLS와 암호화 코드까지 포함해 모든 줄을 작성했습니다. 판단은 27년 경력의 엔지니어 JT Turner가 내렸습니다. Claude가 TLS를 직접 작성하는 데 이의를 제기했을 때 내건 조건은 이것이었습니다: 믿지 않는 것처럼 테스트하라. 그래서 모든 "동작한다"는 다른 이의 테스트로 확인합니다. Wycheproof, RFC, 그리고 npm, pnpm, yarn, bun의 테스트 스위트입니다.

결정은 숫자가 합니다. HTTP/2 클라이언트를 만들어 GitHub 러너와 데스크톱에서 벤치마크했더니 더 느리고 CPU도 더 많이 써서, 삭제했습니다.

jpm은 완벽할까요? 아닙니다. 완벽이란 존재하지 않습니다. 충분히 좋은 것이 있고, 훌륭한 것이 있고, 지금 가진 게 어느 쪽인지 알 만큼 충분히 테스트한 것이 있을 뿐입니다.

JT Turner

전체 이야기 읽기

CI에서 jpm을 써 보세요. 그리고 시간이 없다고 생각했던 그것을 만들러 가세요.

jpm 설치