노트

npm과 pnpm

npm vs pnpm

프런트엔드#tooling · 연결된 개념 7개

쉽게 말하면

npm은 프로젝트마다 같은 책을 한 권씩 사서 꽂는다면, pnpm은 서재에 한 권만 두고 각 프로젝트엔 그 책을 가리키는 링크만 걸어 두는 방식이에요. 같은 패키지를 한 벌만 저장해 디스크와 설치 시간을 아껴요.

비유가 깨지는 곳 pnpm은 아끼기만 하는 게 아니라 엄격하기도 해요. 직접 선언한 패키지만 import되게 해서 npm에서 우연히 동작하던 유령 의존성을 막아요. 대신 평평한 구조를 가정한 일부 도구에선 드물게 문제가 나요.

npm과 pnpm은 둘 다 Node.js 패키지 매니저(Package Manager)다. 가장 큰 차이는 의존성을 디스크에 두는 방식이다. npm은 프로젝트마다 패키지를 복사해 평평한 node_modules를 만들고, pnpm은 전역 저장소에 한 번만 저장하고 프로젝트에는 링크만 건다.

npm: 평평한 node_modules

  • 프로젝트가 10개면 같은 버전의 lodash가 10번 복사된다
  • 의존성을 최상단으로 끌어올리는(Hoisting) 덕분에, package.json에 없는 패키지도 import하면 우연히 동작한다. 다른 패키지가 끌고 온 것을 몰래 쓰는 유령 의존성(Phantom Dependency)이다. 그 패키지가 버전을 바꾸거나 빠지면 갑자기 깨진다(하이럼의 법칙)
  • 같은 라이브러리의 여러 버전이 중복 설치되면 npm dedupe로 줄인다. semver(Semantic Versioning)를 지킨다고 가정하고 호환되는 높은 버전 하나로 합친다(번들 크기 줄이기)

pnpm: 저장소 + 링크

  • 패키지를 내용 기반 전역 저장소(content-addressable store)에 한 번만 저장하고, 각 프로젝트의 node_modules에는 하드 링크(Hard Link)와 심볼릭 링크(Symbolic Link)만 둔다
  • 디스크 절약: 같은 버전은 컴퓨터 전체에서 한 벌이다
  • 설치 속도: 이미 저장소에 있으면 내려받지 않고 링크만 건다
  • 엄격함: 직접 선언한 의존성만 접근할 수 있게 구성해 유령 의존성을 구조적으로 막는다
npmpnpm
기본 제공Node.js에 포함별도 설치
저장 방식프로젝트마다 복사전역 저장소 + 링크
유령 의존성가능차단
워크스페이스지원지원(엄격성 덕에 대규모에 유리)

같은 package.json을 쓰고 명령도 거의 같아(npm install → pnpm install) 옮기기 쉽다. 평평한 구조를 가정한 일부 도구에서 드물게 문제가 난다. 여러 패키지를 한 저장소에서 다루는 구성은 pnpm 워크스페이스·모노레포·Turborepo·Nx 참고.

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • NestJS

    NestJS는 TypeScript를 전제로 모듈·의존성 주입(Dependency Injection, DI)·데코레이터(decorator) 구조를 제공하는 Node.js 서버 프레임워크다. 2017년 Kamil Myśliwiec가 만들었고, 구조를 강제하는 방식 때문에 흔히 "Node.js의 Spring"이라 불린다.

  • 파이썬 모듈과 패키지

    파이썬에서 .py 파일 하나가 모듈(module)이고, 모듈을 모은 디렉터리가 패키지(package)다. import는 다른 모듈의 변수·함수·클래스에 접근할 수 있게 해 주고, 모듈은 처음 import될 때 한 번만 실행된 뒤 캐시된다(sys.modules).

  • Pages Router에서 App Router로

    App Router는 Next.js 13에서 도입된 app/ 디렉터리 기반 라우터로, 서버 컴포넌트·중첩 레이아웃(Nested Layouts)·스트리밍을 기본으로 한다. pages/ 기반의 Pages Router에서 옮길 때 바뀌는 생각을 정리한다.

  • LRU 캐시와 캐시 계층 비교

    LRU(Least Recently Used) 캐시는 크기를 정해 두고, 가득 차면 가장 오랫동안 쓰지 않은 항목부터 버리는 메모리 캐시다. Node.js에서는 lru-cache 패키지가 대표적이다. 자주 쓰는 데이터는 계속 남고 안 쓰는 것만 밀려난다.

  • 배럴 파일과 re-export

    배럴 파일(Barrel File)은 여러 모듈의 export를 index.ts 하나에 모아 다시 내보내(re-export) 진입점을 하나로 만드는 파일이다. 쓰는 쪽은 import { Button, Input } from './components'처럼 한 경로에서 가져온다.

보기 옵션