2026 JavaScript 패키지 매니저 비교: npm, yarn, pnpm, Bun
npm, yarn, pnpm, Bun 네 가지 패키지 매니저의 설치 속도, 디스크 효율, 보안, 모노레포 지원을 벤치마크 수치와 함께 비교하고 상황별 선택 가이드를 제시합니다.
npm install을 실행하고 터미널을 멍하니 바라본 경험, 누구나 한 번쯤 있을 겁니다. 소규모 프로젝트에서는 10초 남짓이면 끝나지만, 의존성이 800개를 넘는 모노레포에서는 2분 이상 걸리기도 합니다. CI/CD 파이프라인이 하루에 수십 번 돌아간다면, 이 시간은 곧 비용입니다.
2026년 현재 JavaScript 패키지 매니저 선택은 단순한 취향 문제가 아닙니다. 설치 속도, 디스크 사용량, 보안, 모노레포 지원 까지 프로젝트 인프라 전반에 영향을 미치는 기술적 결정이 되었습니다. npm만 써왔다면 지금이 대안을 검토할 좋은 시점입니다. 함께 살펴보겠습니다.
4대 패키지 매니저 한눈에 보기
본격적인 비교에 앞서 각 패키지 매니저의 현황과 핵심 특징을 간략히 정리하겠습니다.
| 패키지 매니저 | 최신 버전 | GitHub 스타 | 핵심 특징 |
|---|---|---|---|
| npm | v11.7+ | ~9,400 | Node.js 기본 탑재, 최대 호환성 |
| yarn (Berry) | v4.12 | ~41,500 | PnP Zero-Install, 플러그인 시스템 |
| pnpm | v10.32+ | ~33,500 | content-addressable store, 엄격한 의존성 |
| Bun | v1.3.x | ~77,000+ | Zig 기반 네이티브, All-in-one 통합 |
npm 은 Node.js와 함께 설치되는 기본 패키지 매니저입니다. 별도 설치가 필요 없고 모든 튜토리얼과 CI 파이프라인이 npm을 기준으로 작성되어 있어 호환성 면에서 압도적입니다. 다만 설치 속도와 디스크 효율 면에서 뒤처집니다.
yarn 은 Facebook(현 Meta)이 npm의 한계를 극복하기 위해 만든 패키지 매니저입니다. v2부터 Berry라는 이름으로 완전히 재작성되었고, PnP(Plug'n'Play) 모드를 통해 node_modules 없이 의존성을 관리하는 독자적인 접근을 취합니다.
pnpm 은 content-addressable store라는 혁신적인 저장 방식으로 디스크 사용량을 극적으로 줄입니다. v10에서는 보안 기본값을 대폭 강화하며 "Security by Default" 철학을 내세우고 있습니다.
Bun 은 Zig로 작성된 네이티브 바이너리로, 패키지 매니저뿐 아니라 런타임, 번들러, 테스트 러너까지 통합한 All-in-one 도구입니다. npm 대비 최대 30배 빠른 설치 속도를 자랑합니다.
동작 원리의 차이
각 패키지 매니저는 의존성을 저장하고 관리하는 방식이 근본적으로 다릅니다. 이 차이가 성능과 보안의 차이로 이어집니다.
npm — 평탄화(Hoisting)
npm은 node_modules를 평탄화하여 설치합니다. 이 방식은 간단하지만 phantom dependency 문제를 일으킵니다. package.json에 명시하지 않은 패키지도 node_modules 최상위에 올라와 import할 수 있게 되는 것입니다.
# npm의 node_modules 구조
node_modules/
├── react/
├── lodash/ # 직접 의존하지 않아도 접근 가능 (phantom dependency)
└── some-package/
나중에 어떤 의존성이 lodash를 제거하면 갑자기 프로젝트 빌드가 깨질 수 있습니다. 직접 선언하지 않은 패키지에 의존하고 있었으니까요.
pnpm — Content-Addressable Store
pnpm은 이 문제를 구조적으로 해결합니다. 패키지 파일을 글로벌 스토어(~/.local/share/pnpm/store/)에 해시 기반으로 저장하고, 프로젝트에는 hard link와 symlink로 연결합니다.
# pnpm의 node_modules 구조
node_modules/
├── .pnpm/ # 실제 패키지 (hard link from global store)
│ ├── react@19.0.0/
│ └── lodash@4.17.21/
├── react -> .pnpm/react@19.0.0/node_modules/react # symlink
└── (직접 의존성만 접근 가능)
이 구조의 장점은 명확합니다. 10개 프로젝트에서 react@19를 사용해도 디스크에는 딱 1벌만 존재합니다. 버전이 다른 경우에도 변경된 파일만 추가 저장합니다. 그리고 직접 의존성만 node_modules 최상위에 노출하므로 phantom dependency가 원천 차단됩니다.
yarn — PnP(Plug'n'Play)
yarn Berry는 더 급진적인 접근을 취합니다. node_modules 자체를 제거하고, .pnp.cjs 파일이 Node.js에게 각 패키지의 디스크 위치를 알려주는 방식으로 동작합니다.
# yarn PnP 구조
.yarn/
├── cache/ # zip 아카이브로 패키지 저장
│ ├── react-npm-19.0.0-xxxx.zip
│ └── lodash-npm-4.17.21-xxxx.zip
└── releases/
.pnp.cjs # 패키지 위치 맵핑 파일
.yarn/cache/를 Git에 커밋하면 CI에서 install 자체가 필요 없는 Zero-Install 이 가능합니다. 네트워크 의존성을 완전히 제거할 수 있다는 점은 매력적이지만, 일부 패키지가 PnP와 호환되지 않는 문제가 있어 nodeLinker: node-modules로 전환해야 할 때도 있습니다.
Bun — 네이티브 속도
Bun은 npm 호환 node_modules를 생성하되, Zig로 작성된 네이티브 바이너리의 장점을 살려 병렬 다운로드와 시스템 콜 최적화로 극한의 속도를 달성합니다.
성능 벤치마크
수치로 확인해 보겠습니다. 아래는 2026년 1월 기준 벤치마크 결과입니다.
Cold Install (캐시/lockfile 없음)
| 프로젝트 규모 | npm | yarn | pnpm | Bun |
|---|---|---|---|---|
| 소규모 (50 deps) | 14.3s | 6.8s | 4.2s | 0.8s |
| 중규모 (200 deps) | 46.1s | 18.2s | 12.4s | 2.1s |
| 대규모 모노레포 (800 deps) | 134.2s | 52.3s | 28.6s | 4.8s |
대규모 모노레포에서 npm이 2분 넘게 걸리는 동안 Bun은 5초면 끝납니다. pnpm도 npm 대비 약 3.7배 빠르고, yarn은 약 2.6배 빠릅니다.
Warm Install (캐시 + lockfile 있음)
| 규모 | npm | yarn (PnP) | pnpm | Bun |
|---|---|---|---|---|
| 소규모 | 3.2s | 0.0s (zero-install) | 1.1s | 0.3s |
| 대규모 | 24.6s | 0.0s (zero-install) | 8.4s | 1.2s |
yarn PnP의 Zero-Install은 의존성을 Git에 커밋하므로 warm install 시간이 말 그대로 0초입니다. Bun은 캐시 히트 시에도 여전히 가장 빠른 축에 속합니다.
디스크 사용량
디스크 효율은 여러 프로젝트를 관리할 때 체감이 큽니다.
| PM | 단일 프로젝트 (200 deps) | 10개 프로젝트 (60% 겹침) |
|---|---|---|
| npm | 487 MB | 4,870 MB |
| yarn (PnP) | 178 MB | ~1,420 MB |
| pnpm | 124 MB (links) | 612 MB (-87%) |
| Bun | 461 MB | ~4,610 MB |
pnpm의 content-addressable store는 프로젝트가 많을수록 진가를 발휘합니다. 10개 프로젝트에서 npm이 약 4.9GB를 차지할 때 pnpm은 612MB로 87%를 절약 합니다.
CI/CD 환경 (GitHub Actions)
| PM | 설치 시간 | 캐시 히트 시 |
|---|---|---|
| npm | 48s | 12s |
| yarn | 21s | 8s |
| pnpm | 14s | 4s |
| Bun | 3s | 1s |
CI에서의 설치 시간은 곧 비용입니다. Bun으로 전환하면 npm 대비 설치 시간을 1/16로 줄일 수 있습니다.
핵심 기능 심층 비교
모노레포 지원
모노레포를 운영한다면 워크스페이스 기능의 성숙도가 중요합니다.
| 기능 | npm | yarn | pnpm | Bun |
|---|---|---|---|---|
| 워크스페이스 프로토콜 | X | O | O | O |
| 선택적 설치 | X | O | O | O |
| 병렬 태스크 실행 | X | O | O | O |
| 필터링 지원 | X | O | O | X |
| 워크스페이스 constraints | X | O | X | X |
pnpm과 yarn이 가장 풍부한 모노레포 기능을 제공합니다. 특히 pnpm의 필터링 기능은 대규모 모노레포에서 특정 패키지만 빌드하거나 테스트할 때 유용합니다.
# pnpm 워크스페이스 설정 (pnpm-workspace.yaml)
packages:
- 'packages/*'
- 'apps/*'
# 특정 워크스페이스만 설치/실행
pnpm --filter @myapp/web install
pnpm --filter @myapp/web dev
# 의존 관계에 있는 패키지도 함께 빌드
pnpm --filter @myapp/web... build
보안
공급망 공격이 해마다 증가하면서 패키지 매니저의 보안 기능이 그 어느 때보다 중요해졌습니다.
| 기능 | npm | yarn | pnpm | Bun |
|---|---|---|---|---|
audit 명령어 | O | O | O | X |
| 스크립트 기본 차단 | X | X | O (v10) | X |
| 패키지 출처 검증 (provenance) | O | X | X | X |
minimumReleaseAge | X | X | O | X |
| phantom dependency 차단 | X | O (PnP) | O | X |
pnpm v10 은 보안 면에서 가장 적극적인 행보를 보이고 있습니다. postinstall 스크립트를 기본적으로 차단하여 공급망 공격의 주요 경로를 원천 봉쇄합니다. minimumReleaseAge 설정으로 출시된 지 일정 시간이 지나지 않은 패키지의 설치를 거부할 수도 있습니다.
# .npmrc (pnpm 보안 설정 예시)
onlyBuiltDependencies:
- fsevents
- esbuild
- sharp
minimumReleaseAge: 24h
npm 은 trusted publishing과 Sigstore 기반 provenance 검증으로 다른 방향에서 보안을 강화하고 있습니다. 패키지가 어디서 빌드되고 배포되었는지 출처를 추적할 수 있습니다.
Bun 은 내장 audit 명령어가 없어 보안 면에서 아쉬운 점이 있습니다. 별도의 서드파티 도구를 활용해야 합니다.
Lock 파일
코드 리뷰에서 lock 파일의 변경 사항을 확인할 수 있는지도 팀 협업에서 중요한 포인트입니다.
| PM | lock 파일 | 형식 | diff 가능 여부 |
|---|---|---|---|
| npm | package-lock.json | JSON | O |
| yarn | yarn.lock | YAML-like | O |
| pnpm | pnpm-lock.yaml | YAML | O |
| Bun | bun.lockb (기본) | 바이너리 | X |
| Bun | bun.lock (옵션) | JSON | O |
Bun의 기본 lock 파일인 bun.lockb는 바이너리 형식이라 Git diff가 불가능합니다. 팀 프로젝트에서는 텍스트 기반 lock 파일을 사용하는 것이 좋습니다.
# Bun에서 텍스트 lock 파일 사용하기
bun install --save-text-lockfile
또는 bunfig.toml에서 설정할 수 있습니다.
[install]
saveLockfile = "text"
실전: 마이그레이션 가이드
기존 npm 프로젝트를 pnpm이나 Bun으로 마이그레이션하는 과정을 알아보겠습니다. 생각보다 간단합니다.
npm에서 pnpm으로
# 1. pnpm 설치 (Corepack 사용 권장)
corepack enable
corepack prepare pnpm@latest --activate
# 2. lock 파일 변환 — 기존 의존성 트리를 그대로 가져옵니다
pnpm import
# 3. node_modules 삭제 후 재설치
rm -rf node_modules
rm package-lock.json
pnpm install
# 4. package.json에 packageManager 필드 추가 (팀 전체 버전 통일)
# "packageManager": "pnpm@10.32.1"
# 5. CI/CD 스크립트 변경
# npm install → pnpm install
# npm run build → pnpm build
# npx → pnpm dlx
pnpm import 명령어가 package-lock.json을 읽어 pnpm-lock.yaml로 변환해 주므로 의존성 트리가 달라질 걱정은 없습니다. 가장 주의할 점은 phantom dependency입니다. package.json에 선언하지 않았지만 코드에서 import하고 있던 패키지가 있다면 pnpm으로 전환 후 에러가 발생합니다. 이때는 해당 패키지를 package.json에 명시적으로 추가하면 됩니다.
npm에서 Bun으로
# 1. Bun 설치
curl -fsSL https://bun.com/install | bash
# 또는 macOS에서
brew install oven-sh/bun/bun
# 2. 의존성 설치 (package.json 그대로 사용)
rm -rf node_modules
bun install # package-lock.json을 자동으로 읽어 의존성을 해석합니다
# 3. 텍스트 lock 파일 사용 (팀 프로젝트 권장)
bun install --save-text-lockfile
# 4. 스크립트 변경
# npm run dev → bun run dev
# npx → bunx
# npm test → bun test (Bun 내장 테스트 러너 사용 시)
Bun은 기존 package.json과 npm 호환 node_modules 구조를 그대로 사용하므로 마이그레이션이 매우 간단합니다. 다만 Bun의 런타임 자체를 사용하는 것과 패키지 매니저만 사용하는 것은 구분해서 생각해야 합니다. Node.js 런타임은 유지하면서 패키지 매니저만 Bun으로 교체하는 것도 가능합니다.
Bun의 All-in-one 통합
Bun이 다른 패키지 매니저와 근본적으로 다른 점은 패키지 매니저 이상의 역할 을 한다는 것입니다.
# 패키지 매니저
bun install
bun add react
# 런타임 (Node.js 대체)
bun run src/index.ts # TypeScript 직접 실행
bun --hot src/server.ts # Hot reload
# 번들러
bun build ./src/index.ts --outdir ./dist
# 테스트 러너 (Jest/Vitest 대체)
bun test
# npx 대체
bunx create-next-app
하나의 도구로 개발 환경 전체를 커버할 수 있다는 것은 분명한 장점입니다. 하지만 Bun 런타임의 Node.js API 호환성이 아직 100%는 아니라는 점, 보안 감사 도구가 내장되어 있지 않다는 점은 프로덕션 도입 전에 반드시 확인해야 할 부분입니다.
2026년 주요 신기능
각 패키지 매니저가 2026년에 내놓은 주목할 만한 기능들을 정리합니다.
pnpm v10
- Global Virtual Store:
enableGlobalVirtualStore: true설정으로 프로젝트 간 의존성을 글로벌로 공유하여 디스크 효율을 한층 끌어올립니다. - JSR 레지스트리 지원:
jsr:프로토콜로 JSR 패키지를 직접 설치할 수 있습니다. - Config Dependencies: 모노레포에서 pnpm 설정(hooks, patches, build permissions)을 중앙에서 관리합니다.
npm v11
- Bulk Trusted Publishing:
npm trust명령어로 여러 패키지의 OIDC 설정을 일괄 관리합니다. - --allow-git 플래그: Git 의존성의 보안 위험을 세밀하게 제어합니다.
yarn v4.12
- 개선된 TypeScript 통합
- JavaScript 기반 constraints 엔진으로 워크스페이스 규칙을 프로그래밍 방식으로 정의할 수 있습니다.
Bun v1.3
- 풀스택 개발 기능 강화
- 워크스페이스 필터링 개선
사용 사례별 추천
어떤 패키지 매니저가 "최고"인지는 상황에 따라 다릅니다. 프로젝트의 규모, 팀 구성, 우선순위에 따라 적합한 선택이 달라집니다.
새 프로젝트 시작
모노레포인가요?
최우선 순위는?
Zero-Install 필요?
- · 개인/사이드 프로젝트
- · CI/CD 속도 최우선
- · All-in-one 환경 선호
- · 대규모 모노레포
- · 보안이 최우선
- · 디스크 절약 필요
- · 네트워크 없는 CI
- · Zero-Install 필요
- · PnP 도입 가능 팀
- · 레거시/엔터프라이즈
- · 호환성 최우선
- · 별도 설치 불가 환경
개인 프로젝트 / 사이드 프로젝트
Bun 을 추천합니다. 설치 속도가 압도적이고, 런타임과 테스트 러너까지 통합되어 있어 도구 설정에 시간을 쓰지 않아도 됩니다. 보안 감사가 덜 중요한 개인 프로젝트에서 Bun의 약점은 크게 드러나지 않습니다.
대규모 모노레포
pnpm 이 가장 적합합니다. 워크스페이스 필터링, 엄격한 의존성 관리, 디스크 효율 모두 모노레포에 최적화되어 있습니다. Turborepo와의 조합도 검증되어 있습니다.
엔터프라이즈 / 레거시 프로젝트
npm 이 안전한 선택입니다. 별도 설치가 필요 없고, npm audit fix 자동 수정 기능과 trusted publishing으로 보안 거버넌스를 갖출 수 있습니다. 기존 CI/CD 파이프라인과의 호환성도 보장됩니다.
보안이 최우선인 프로젝트
pnpm 을 추천합니다. v10의 postinstall 스크립트 기본 차단과 minimumReleaseAge 설정은 현재 패키지 매니저 중 가장 강력한 보안 기본값입니다.
CI/CD 비용 절감이 목표
Bun (절대 속도)과 pnpm (캐시 효율)을 상황에 따라 선택합니다. CI 환경에서 Bun은 npm 대비 설치 시간을 48초에서 3초로 줄일 수 있습니다.
네트워크 없는 CI 환경
yarn PnP 의 Zero-Install이 유일한 해답입니다. 의존성을 Git에 커밋하면 CI에서 네트워크 접속 자체가 불필요합니다.
주요 프레임워크의 지원 현황
패키지 매니저를 선택할 때 사용하는 프레임워크의 지원 여부도 확인해야 합니다.
- Next.js: npm, yarn, pnpm, Bun 모두 공식 지원합니다.
create-next-app에서 원하는 PM을 선택할 수 있습니다. - Vite: 내부 개발에 pnpm을 사용하며, 공식 문서에서 pnpm 예시를 우선 표기합니다.
- Vercel: 2025년부터 pnpm v10 자동 감지를 지원합니다.
- Turborepo: npm, yarn, pnpm을 공식 지원합니다. Bun은 실험적 지원 단계입니다.
마무리
네 가지 패키지 매니저를 다양한 관점에서 살펴봤습니다. 각각의 강점을 한 줄로 요약하면 이렇습니다.
- npm: 별도 설치 없이 어디서나 동작하는 안정성과 호환성
- yarn: PnP Zero-Install로 네트워크 의존성을 제거하는 독자적 접근
- pnpm: 디스크 효율과 보안 기본값을 모두 잡은 균형 잡힌 선택
- Bun: 압도적인 속도와 All-in-one 통합으로 개발 경험을 단순화
"어떤 것이 최고인가"보다 "우리 프로젝트에 어떤 것이 적합한가" 를 기준으로 판단하는 것이 중요합니다. npm만 써왔다면 pnpm이나 Bun을 사이드 프로젝트에서 먼저 시도해 보는 것을 권합니다. 마이그레이션은 생각보다 간단하고, 체감되는 속도 차이는 상당합니다.
패키지 매니저는 매일 사용하는 도구입니다. 조금 더 나은 도구를 선택하는 것이 장기적으로 개발 경험에 큰 차이를 만들어줄 것입니다.