성능적으로 느리고 의존성 중복 저장문제를 호이스팅(hoisting)을 통해 해결한다. 이에 따라 유령 의존성 현상이 발생할 수 있다.
즉, 현재 프로젝트에 직접적으로 필요 없는 패키지에 접근을 할 수 있는 문제가 발생할 수도 있다.

출처: https://toss.tech/article/node-modules-and-yarn-berry
디스크 사용 비효율성:
node_modules 폴더에 복사한다. 이로 인해 중복된 패키지가 여러 번 저장되어 디스크 사용량이 증가한다.의존성 충돌 문제:
node_modules 폴더를 관리하지 않아, 특정 버전의 패키지가 요구되는 경우 의존성 충돌이 발생할 수 있다. 이러한 충돌은 디버깅을 어렵게 만든다.디스크 사용 비효율성:
속도 문제:
의존성 문제:
node_modules의 무거움을 표현한 그림

PNPM은 node_modules를 직접 설치하는 대신에 Symbolic Link와 Hard Link를 사용해서 모듈을 관리한다.

Symbolic Link
pnpm을 사용하면 프로젝트 내에 node_modules에 가상 저장소를 가리키는 심볼릭 링크로 구성한다.
가상 저장소는 ./node_modules/.pnpm에 위치한다.
Hard Link
inode를 가지는 링크inode - 시스템의 파티션에 있는 각 파일에 대한 정보를 기억하는 120바이트의 고정된 크기의 구조체inode를 통해서 원본 데이터에 접근하기 때문에 원본 데이터만 사라지지 않는다면 접근 가능한 것이다.pnpm store에 저장된 패키지나, node_modules/.pnpm에 저장된 패키지나 동일한 데이터(동일한 inode)를 참조하고 있다. (하드링크를 통해)
pnpm store path를 통해 스토어의 위치를 확인할 수 있다.

결론적으로, pnpm은 디스크의 세 위치를 사용하면서 용량을 줄인다.
저장소와 가상 저장소는 같은
inode를 바라 보고 있는 점 다시 한번 기억하자.
컨테이너와 이미지에 대한 개념을 그림를 통해 참고하자.

pnpm 공식 문서를 보면 다음과 같이 도커 파일을 구성해두고 있는 예시가 있다.
FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build
FROM base
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist
EXPOSE 8000
CMD [ "pnpm", "start" ]
몰랐던 각 옵션을 살펴보자.
BuildKit 캐시가 어떤 구조로 동작하는 지는 아래 이미지를 참고하자.



BuildKit은 도커 18.09 버전부터 지원이 되고 도커의 빌더로서 도커 데스크탑 또는 23 버전부터 기본 빌더로 내장되어 있다. (참고)
그 이하 버전을 사용한다면 이미지 빌드 시에 다음과 같이 DOCKER_BUILDKIT=1를 추가해서 빌드해주자.
DOCKER_BUILDKIT=1 docker build -t my-image:tag .