pnpm vs npm vs Yarn — 2026년엔 뭘 써야 하나?

pnpm vs npm vs Yarn

항목 npm Yarn v4 pnpm
설치 속도 보통 빠름 🏆 가장 빠름
디스크 사용량 많음 보통 🏆 가장 적음
모노레포 지원 workspaces ✅ workspaces ✅ workspaces ✅
Node.js 기본 내장 ✅ 기본 포함 별도 설치 별도 설치
유령 의존성 차단 △ (PnP 모드) ✅ 기본 차단
CI/CD 캐시 효율 보통 좋음 🏆 최고
러닝 커브 낮음 중간 낮음

npm — 여전히 무난한 기본값

Node.js를 설치하면 자동으로 따라오는 npm은 여전히 업계 표준입니다. v7부터 workspaces를 지원하고, v9/v10에서 속도도 꽤 빨라졌습니다. 처음 Node.js를 배우는 사람이나 팀원들 환경을 맞추기 귀찮을 때는 npm이 가장 편합니다.

문제는 유령 의존성(phantom dependency)입니다. npm은 node_modules를 플랫하게 호이스팅하기 때문에, package.json에 없는 패키지를 import해도 런타임에 동작합니다. 이게 나중에 패키지 버전이 바뀌면 조용히 터집니다. 직접 겪어봤는데 원인 찾는 데 한참 걸렸습니다.

npm이 적합한 경우

  • 소규모 프로젝트: 의존성이 단순하고 빠른 셋업이 우선일 때
  • CI 환경이 npm으로 고정된 팀: 기존 스크립트를 바꾸기 어려울 때
  • 입문자: 패키지 매니저 개념을 처음 배울 때 가장 많은 레퍼런스 활용 가능

Yarn v4 — Berry에서 많이 달라졌습니다

Yarn 1.x(Classic)는 이미 레거시입니다. 요즘 새 프로젝트에 Yarn을 쓴다면 v4 (Berry)를 써야 합니다. Corepack으로 버전을 고정해 팀 전체가 같은 버전을 쓰도록 강제할 수 있고, Zero-Install 모드로 .yarn/cache를 git에 커밋하면 yarn install 없이 바로 실행도 가능합니다.

Yarn PnP(Plug'n'Play) 모드는 node_modules 폴더 자체를 없애버립니다. 유령 의존성을 원천 차단하는 방식인데, 문제는 일부 도구들(특히 오래된 Webpack 설정이나 Jest 플러그인)이 PnP와 충돌합니다. 실제로 Next.js + Yarn PnP 조합을 써봤는데 플러그인 하나 추가할 때마다 `.yarnrc.yml` 설정을 건드려야 해서 번거로웠습니다.

Yarn이 적합한 경우

  • Turborepo + 모노레포: Turborepo 공식 예제가 Yarn 기반으로 많이 나와 있습니다
  • Zero-Install 전략이 필요한 팀: CI 속도보다 오프라인 재현성이 중요할 때
  • 기존 Yarn 프로젝트 유지보수: 이미 쓰고 있다면 굳이 바꿀 이유는 없습니다

pnpm — 2026년 내가 기본값으로 쓰는 이유

pnpm의 핵심은 content-addressable storage다. 전역 저장소에 패키지를 한번만 저장하고, 프로젝트마다 하드링크/심링크로 연결합니다. React 18을 10개 프로젝트에서 쓴다고 해도 디스크에는 한 번만 들어갑니다. 개발 머신에서 프로젝트가 쌓일수록 효과가 극적으로 달라집니다.

속도도 npm 대비 체감상 30~50% 빠릅니다. 특히 node_modules가 이미 캐시된 상태에서 재설치할 때 차이가 큽니다. GitHub Actions에서 ~/.pnpm-store를 캐시하면 CI 시간도 눈에 띄게 줄어듭니다.

pnpm의 유령 의존성 차단

pnpm은 node_modules 구조 자체가 다릅니다. 실제로 package.json에 명시된 패키지만 최상위 node_modules에 노출되고, 나머지는 .pnpm 폴더 안에 격리됩니다. 덕분에 선언하지 않은 패키지를 import하면 바로 에러가 납니다. 처음엔 당황스러웠지만 결국 의존성이 명확해져서 좋습니다.

모노레포에서의 pnpm

Turborepo, Nx 모두 pnpm workspaces를 공식 지원합니다. 특히 Turborepo + pnpm 조합은 현재 내가 사내 모노레포에 사용 중인데, pnpm-workspace.yaml 설정이 간결하고 패키지 간 의존성 관리가 직관적입니다.


🏎️ 실제 설치 속도 비교 (2026 기준)

동일한 Next.js + Tailwind CSS 프로젝트(package.json 의존성 약 45개)를 캐시 없는 상태에서 설치했을 때 대략적인 시간입니다. 환경마다 다를 수 있지만 상대적인 비율은 비슷하게 나옵니다.

시나리오 npm Yarn v4 pnpm
캐시 없음 (cold install) ~45초 ~32초 ~22초
캐시 있음 (warm install) ~18초 ~12초 ~6초
lockfile 변경 없음 (no changes) ~8초 ~4초 ~2초

npm → pnpm 마이그레이션 방법

생각보다 간단합니다. 대부분의 프로젝트에서 아래 과정으로 5분 안에 전환됩니다.

# 1. pnpm 설치 (Corepack 사용 권장)
corepack enable
corepack prepare pnpm@latest --activate

# 2. 기존 node_modules, lock 파일 제거
rm -rf node_modules package-lock.json

# 3. pnpm으로 재설치
pnpm install

# 4. 스크립트 확인 (npm run dev → pnpm dev)
pnpm dev

주의할 점은 유령 의존성이 있던 프로젝트라면 마이그레이션 직후 에러가 날 수 있습니다. 이때는 pnpm add [패키지명]으로 실제로 필요한 패키지를 명시적으로 추가해 주시면 됩니다. 이 과정이 번거롭지만 오히려 의존성을 정리하는 기회가 됩니다.


Bun의 패키지 매니저 기능은?

Bun도 패키지 매니저 기능을 내장하고 있고 속도는 pnpm보다 빠릅니다. 하지만 Bun은 런타임 자체를 교체하는 결정이라 프로젝트 전체에 영향을 줍니다. 단순히 패키지 매니저만 바꾸고 싶다면 pnpm이 더 현실적인 선택입니다. Bun vs Node.js 비교는 따로 정리했으니 참고하자.


✅ 내 선택 — 2026년엔 pnpm이 기본값

지금 당장 어떤 걸 써야 하냐고 묻는다면 대답은 명확합니다.

  • 새 프로젝트 시작: pnpm. 설치 속도, 디스크 효율, 유령 의존성 차단까지 세 마리 토끼를 잡을 수 있습니다.
  • 기존 npm 프로젝트: 당장 바꿀 이유가 없으면 그냥 사용해도 됩니다. 단, 모노레포로 확장할 계획이 있다면 pnpm으로 미리 옮기자.
  • Yarn 1.x 유지 중: 빨리 벗어나자. Yarn Classic은 더 이상 업데이트가 없습니다. pnpm이나 Yarn v4 중 하나로 마이그레이션을 추천합니다.

팀 규모가 커질수록, CI를 자주 돌릴수록 pnpm의 이점이 복리로 쌓입니다. 나는 사이드 프로젝트부터 사내 모노레포까지 모두 pnpm으로 통일했습니다.


🔗 관련 글

댓글