pnpm vs npm vs yarn 완전 비교 2026 — 개발자를 위한 패키지 매니저 선택 가이드
pnpm, npm, yarn의 속도·디스크 효율·모노레포 지원을 2026년 기준으로 비교합니다. 프로젝트 규모와 팀 상황에 맞는 패키지 매니저 선택 기준과 pnpm 마이그레이션 방법을 정리했습니다.
패키지 매니저 선택이 개발 경험을 바꾼다
Node.js 생태계의 패키지 매니저는 npm, yarn, pnpm 세 가지가 주류입니다. 2026년 현재 pnpm이 속도와 디스크 효율, 모노레포 지원에서 두각을 나타내며 채택이 빠르게 늘고 있습니다.
한눈에 비교
| 항목 | npm v10 | yarn v1 (classic) | yarn berry (v4) | pnpm v9 |
|---|---|---|---|---|
| 설치 속도 | 기준 | 빠름 | 빠름 (PnP) | 가장 빠름 |
| 디스크 사용 | 높음 | 높음 | 낮음 (PnP) | 가장 낮음 |
| node_modules | 플랫 호이스팅 | 플랫 호이스팅 | 없음 (PnP) | 엄격한 심볼릭링크 |
| 모노레포 | workspaces 지원 | workspaces 지원 | workspaces 지원 | 최고 수준 |
| 호환성 | 최고 | 높음 | 중간 (PnP 이슈) | 높음 |
| 팬텀 의존성 방지 | X | X | O (PnP) | O |
| 학습 난이도 | 쉬움 | 쉬움 | 어려움 | 쉬움 |
pnpm이 빠른 이유: 콘텐츠 주소 저장소
npm/yarn의 방식
프로젝트 A: node_modules/react@18.3.0 (복사본 1)
프로젝트 B: node_modules/react@18.3.0 (복사본 2)
프로젝트 C: node_modules/react@18.3.0 (복사본 3)
→ 디스크에 react 3개 복사본 존재
pnpm의 방식
~/.pnpm-store/v3/files/... (전역 저장소, 1개만 존재)
↑ 하드링크
프로젝트 A: node_modules/.pnpm/react@18.3.0/
↑ 심볼릭링크
프로젝트 A: node_modules/react → .pnpm/react@18.3.0/node_modules/react
→ 실제 파일은 한 번만 저장, 참조만 공유
실제 측정 결과 (react + 100개 의존성 프로젝트 기준)
| 작업 | npm | yarn v1 | pnpm |
|---|---|---|---|
| 최초 설치 (캐시 없음) | 45s | 38s | 28s |
| 재설치 (캐시 있음) | 22s | 12s | 5s |
| CI 환경 (캐시 없음) | 40s | 35s | 18s |
| 디스크 사용량 | 250MB | 240MB | 80MB |
설치 및 기본 명령어
pnpm 설치
# npm을 통한 설치
npm install -g pnpm
# 또는 공식 설치 스크립트 (curl)
curl -fsSL https://get.pnpm.io/install.sh | sh -
# 또는 Homebrew (macOS)
brew install pnpm
# 버전 확인
pnpm --version
명령어 비교
| 작업 | npm | yarn v1 | pnpm |
|---|---|---|---|
| 설치 | npm install | yarn | pnpm install |
| 패키지 추가 | npm install react | yarn add react | pnpm add react |
| 개발 의존성 추가 | npm install -D eslint | yarn add -D eslint | pnpm add -D eslint |
| 패키지 삭제 | npm uninstall react | yarn remove react | pnpm remove react |
| 스크립트 실행 | npm run build | yarn build | pnpm build |
| 전역 설치 | npm install -g pkg | yarn global add pkg | pnpm add -g pkg |
| lock 파일 기반 설치 | npm ci | yarn install --frozen-lockfile | pnpm install --frozen-lockfile |
| 패키지 목록 | npm list | yarn list | pnpm list |
| 업데이트 | npm update | yarn upgrade | pnpm update |
npm에서 pnpm으로 마이그레이션
1단계: pnpm 설치 및 import
# pnpm 설치
npm install -g pnpm
# package-lock.json → pnpm-lock.yaml 변환
pnpm import
# 또는 처음부터 재생성 (더 깨끗한 방법)
rm package-lock.json
pnpm install
2단계: package.json 설정
{
"name": "my-app",
"engines": {
"node": ">=20",
"pnpm": ">=9"
},
"packageManager": "pnpm@9.12.0"
}
3단계: .npmrc 설정
# .npmrc
# 엄격한 node_modules 구조 유지 (권장)
strict-peer-dependencies=false
auto-install-peers=true
# 필요 시 호이스팅 활성화 (호환성 문제 해결용)
# shamefully-hoist=true
4단계: .gitignore 업데이트
# .gitignore에 추가
node_modules
# pnpm-lock.yaml은 커밋 대상 (package-lock.json과 동일)
5단계: CI/CD 업데이트
# GitHub Actions
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Build
run: pnpm build
pnpm 모노레포 설정
pnpm-workspace.yaml
# pnpm-workspace.yaml (루트에 위치)
packages:
- 'apps/*'
- 'packages/*'
- '!**/__tests__/**'
모노레포 디렉토리 구조
my-monorepo/
├── pnpm-workspace.yaml
├── package.json
├── apps/
│ ├── web/ # Next.js 앱
│ │ └── package.json
│ └── api/ # Express 서버
│ └── package.json
└── packages/
├── ui/ # 공유 컴포넌트
│ └── package.json
└── utils/ # 공유 유틸리티
└── package.json
루트 package.json
{
"name": "my-monorepo",
"private": true,
"scripts": {
"dev": "pnpm -r --parallel run dev",
"build": "pnpm -r run build",
"lint": "pnpm -r run lint",
"test": "pnpm -r run test"
},
"devDependencies": {
"turbo": "^2.0.0"
}
}
모노레포 주요 명령어
# 전체 설치
pnpm install
# 전체 빌드
pnpm -r run build
# 특정 패키지만 실행
pnpm --filter @myapp/web dev
pnpm --filter @myapp/api start
# 특정 패키지에 의존성 추가
pnpm --filter @myapp/web add react
pnpm --filter @myapp/web add -D tailwindcss
# 워크스페이스 내 패키지 참조
# apps/web/package.json:
# "dependencies": { "@myapp/ui": "workspace:*" }
Turborepo 연동 (빌드 캐싱)
// turbo.json
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": [".next/**", "dist/**"]
},
"dev": {
"cache": false,
"persistent": true
},
"lint": {
"outputs": []
}
}
}
# Turborepo로 병렬 빌드 + 캐싱
pnpm turbo build
# 변경된 패키지만 빌드 (CI 최적화)
pnpm turbo build --filter='[HEAD^1]'
언제 무엇을 선택할까
pnpm 선택 기준
- 모노레포를 운영하거나 계획 중
- CI 속도와 디스크 효율이 중요
- 팬텀 의존성 문제를 방지하고 싶음
- 새 프로젝트 시작 시 (기본 선택)
npm 유지 기준
- 팀이 npm에 익숙하고 전환 비용이 부담
- 레거시 패키지 호환성이 최우선
- 단순한 소규모 프로젝트
yarn v1 유지 기준
- 기존 yarn v1 프로젝트이고 굳이 전환할 이유 없음
- (yarn v1은 더 이상 활발히 개발되지 않음)
yarn berry 선택 기준
- Zero-Installs 전략이 꼭 필요 (CI 환경 최적화)
- 팀 전체가 PnP 설정에 익숙함
- 기존 yarn berry 프로젝트 유지
자주 겪는 문제와 해결
"Cannot find module" 오류 (팬텀 의존성)
# 문제: package.json에 선언 안 된 패키지에 접근 시
Error: Cannot find module 'lodash'
# 해결: 직접 의존성으로 추가
pnpm add lodash
# 임시 해결 (권장 X): .npmrc에 추가
shamefully-hoist=true
peer dependencies 경고
# 자동 설치 활성화
echo "auto-install-peers=true" >> .npmrc
# 엄격한 peer deps 검사 비활성화 (필요 시)
echo "strict-peer-dependencies=false" >> .npmrc
pnpm store 정리
# 사용하지 않는 패키지 정리
pnpm store prune
# 전체 store 위치 확인
pnpm store path
정리
| npm | pnpm | |
|---|---|---|
| 초보자 진입 장벽 | 낮음 | 낮음 |
| 속도 | 보통 | 빠름 |
| 디스크 효율 | 낮음 | 높음 |
| 모노레포 | 기본 지원 | 강력한 지원 |
| 생태계 호환성 | 최고 | 높음 |
| 2026년 추천도 | ★★★☆☆ | ★★★★★ |
새 프로젝트라면 pnpm, 기존 npm 프로젝트라면 pnpm import 한 줄로 마이그레이션하는 것을 권장합니다.
관련 글: GitHub Actions CI/CD 설정법 · Next.js + MDX 블로그 만들기 · Vercel 무료 배포 완전 가이드
관련 글
Turborepo 모노레포 가이드 2026 — pnpm 워크스페이스 실전 설정
Turborepo와 pnpm 워크스페이스로 모노레포를 구성하는 실전 가이드. 태스크 파이프라인, 원격 캐싱, 공유 패키지 설정까지 처음부터 단계별로 설명합니다.
AWS 비용 최적화 완전 가이드 2026 — EC2, S3, RDS 비용 절감 실전
AWS 비용이 예상보다 많이 나오는 개발자를 위한 최적화 가이드. EC2 Reserved Instance vs Savings Plans, S3 스토리지 클래스, RDS 비용 절감, 무료 티어 한도, 비용 모니터링 설정까지 실전 방법을 정리했습니다.
Git 고급 명령어 실무 가이드 2026 — rebase, stash, cherry-pick 완전 정리
개발자가 실무에서 꼭 알아야 할 Git 고급 명령어를 정리했습니다. rebase vs merge, interactive rebase, stash, cherry-pick, bisect, reflog로 실수 복구까지 실전 예시와 함께 설명합니다.