DevFinance
테크·9 min read

pnpm vs npm vs yarn 완전 비교 2026 — 개발자를 위한 패키지 매니저 선택 가이드

pnpm, npm, yarn의 속도·디스크 효율·모노레포 지원을 2026년 기준으로 비교합니다. 프로젝트 규모와 팀 상황에 맞는 패키지 매니저 선택 기준과 pnpm 마이그레이션 방법을 정리했습니다.

패키지 매니저 선택이 개발 경험을 바꾼다

Node.js 생태계의 패키지 매니저는 npm, yarn, pnpm 세 가지가 주류입니다. 2026년 현재 pnpm이 속도와 디스크 효율, 모노레포 지원에서 두각을 나타내며 채택이 빠르게 늘고 있습니다.


한눈에 비교

항목npm v10yarn v1 (classic)yarn berry (v4)pnpm v9
설치 속도기준빠름빠름 (PnP)가장 빠름
디스크 사용높음높음낮음 (PnP)가장 낮음
node_modules플랫 호이스팅플랫 호이스팅없음 (PnP)엄격한 심볼릭링크
모노레포workspaces 지원workspaces 지원workspaces 지원최고 수준
호환성최고높음중간 (PnP 이슈)높음
팬텀 의존성 방지XXO (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개 의존성 프로젝트 기준)

작업npmyarn v1pnpm
최초 설치 (캐시 없음)45s38s28s
재설치 (캐시 있음)22s12s5s
CI 환경 (캐시 없음)40s35s18s
디스크 사용량250MB240MB80MB

설치 및 기본 명령어

pnpm 설치

# npm을 통한 설치
npm install -g pnpm

# 또는 공식 설치 스크립트 (curl)
curl -fsSL https://get.pnpm.io/install.sh | sh -

# 또는 Homebrew (macOS)
brew install pnpm

# 버전 확인
pnpm --version

명령어 비교

작업npmyarn v1pnpm
설치npm installyarnpnpm install
패키지 추가npm install reactyarn add reactpnpm add react
개발 의존성 추가npm install -D eslintyarn add -D eslintpnpm add -D eslint
패키지 삭제npm uninstall reactyarn remove reactpnpm remove react
스크립트 실행npm run buildyarn buildpnpm build
전역 설치npm install -g pkgyarn global add pkgpnpm add -g pkg
lock 파일 기반 설치npm ciyarn install --frozen-lockfilepnpm install --frozen-lockfile
패키지 목록npm listyarn listpnpm list
업데이트npm updateyarn upgradepnpm 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

정리

npmpnpm
초보자 진입 장벽낮음낮음
속도보통빠름
디스크 효율낮음높음
모노레포기본 지원강력한 지원
생태계 호환성최고높음
2026년 추천도★★★☆☆★★★★★

새 프로젝트라면 pnpm, 기존 npm 프로젝트라면 pnpm import 한 줄로 마이그레이션하는 것을 권장합니다.

관련 글: GitHub Actions CI/CD 설정법 · Next.js + MDX 블로그 만들기 · Vercel 무료 배포 완전 가이드