home

pnpm 2부

글 분류
main
키워드
pnpm
생성일
2022/08/12 11:00
최근 수정일
2025/02/13 01:26
작성중

⚽️ 목표

pnpm쟝... 내가.. 좀더 알아보게 허락해주겠어?
결론이 존재하지 않는 게시글입니다. 그냥 정리하면서 공부하면 더 잘되서 작성한 게시글 입니다.

TL;DR

symlink, hardlink를 이용하여 효율적인 디스크 공간 관리 및 속도를 중요시 하는 패키지 관리자 - 제일 합리적여
결국 돌고돌아(npm -> yarn -> yarn berry) pnpm으로 정착
추가된 pnpm 사용 이유 -> 마이너 감성 완.전.충.족.앗.흥.

1. pnpm 이해에 필요한 기본지식

content-addressable store(CAS)

이름이 너무기니까 이하 CAS로 통일
pnpm store path # ~/pnpm/store/v3 - pnpm 설치 방법마다 다름
Bash
복사
간단히 설명하면 패키지 파일 중앙 저장 관리소 이다. 복잡하게 생각하지말자. → 중앙이라는 키워드가 제일 중요
node_modules의 무거운 패키지 지옥을 해결하는 방법 중 하나.
npm, yarn의 경우
예시) 리액트 18.0.2버전이 10개의 프로젝트에서 사용하고 있다. → npm이나 yarn의 경우 각 프로젝트마다 react 18.0.2가 프로젝트 마다 따로따로 설치되어 있다. 한마디로 같은 파일들의 10개 복사본이 각각 다른 위치에 파일을 보관하고 있음.
여기서 문제점은 똑같은 리소스의 의미없는 저장용량 사용 + 설치 시 때 마다 파일 새로 네트워크에서 다운
문제점 중 하나인 “설치 시 때 마다 파일 새로 네트워크에서 다운”은 최신 버전 패키지 매니저들에서 대부분 “캐싱”을 이용하여 네트워크 요청이 아닌 캐싱된 파일 복사로 진행되어 어느정도 해결된다. 그러나 파일 I/O로 인한 리소스 낭비는 완벽해결을 하지 못한 상태.
“파일 I/O로 인한 리소스낭비..? 야.. 이건 좀 억지아니냐? 그게 얼마나 오래걸리는 작업이라고..” 할 수 있지만 일단 pnpm에 비교했을때 차이가 존재하는건 사실이기 때문에 짚고 넘어가야할 사실이다.
pnpm
pnpm의 CAS에 실제 파일들이 저장되고 프로젝트에서 사용하고자 할때는 CAS에 저장된 파일들을 hardlink해 사용하기 때문에 설치 속도(네트워크 요청, file io가 없기 때문) 및 디스크 저장공간의 효율적인 관리가 가능하다.
쉽게 풀어서 말하자면 “이미 존재하는 파일을 왜 다시받아? 같은 파일인데 그냥 링크해주면 되는거 아냐?”

inode

index-node의 줄임말로 파일에 대한 정보(해당 파일에 대한 소유권, 권한, 타임스탬프, 디스크 내 위치)를 가지고 있는 데이터 구조
ls -i # 138232 node_modules
Bash
복사
파일 시스템에 주민등록번호 -> 파일 시스템 내에 파일, 디렉터리들은 고유한 inode 값을 가지고 있다.
symlink(softlink 라고도 부름, 이하 symlink로 통일)로 연결된 파일은 같은 파일을 바라보고 있다 해도 서로 다른 inode를 가지고 있음

hardlink

다른 파일의 inode를 직접 참조하는 파일
A(원본) 파일이 삭제되더라도 A를 hardlink한 B 파일은 여전히 존재 및 참조 가능
보조기억장치에 저장된 파일 접근 시 inode를 활용하여 직접 접근하므로 symlink보다 성능이 비교적 좋음
디렉터리는 hardlink 불가능하다.
파일들이 하드링크된 파일은 용량을 추가로 갖지 않고 원본파일 하나만 존재한다.

symlink

윈도우의 바로가기와 비슷한 형태로 참조하는 파일
hardlink 처럼 파일을 직접 참조하지 않고, 참조하는 원본파일의 파일의 path를 갖고 있다. → 파일 참조 시 원본 파일을 경유하므로 hardlink에 비해 비교적 속도가 느리다.
A(원본) 파일이 삭제되되면 A를 symlink한 B파일은 참조 불가
디렉터리 symlink 가능

2. 들어가기 전 - npm의 node_modules 구조

npm이 가지고 있는 문제점을 알아야 “구지비 지금 잘 쓰고있는” npm에서 pnpm으로 넘어가지 않겠니?

유령 의존성

# npm의 패키지 설치 방식을 확인을 위한 테스트 프로젝트 초기화 mkdir npm1 npm init -y npm install react
Bash
복사
node_modules 확인 시 호이스팅 된 패키지들을 확인 할 수 있다. → 나는 리액트만 설치했는데 직접 설치하지 않은 jstokens와 loose-envify 라이브러리들이 최상단에 존재한다. 이게 바로 유령 의존성.
cd node_modules ls -a # .package-lock.json, react, js-tokens ,.bin, loose-envify
Bash
복사
js-tokens, loose-envify 패키지가 npm의 shameful 한(pnpm 설정에선 shameful이라면서 뜯어 말리기 까지하는 결과물) 호이스팅의 결과물

.bin 디렉터리

사용자의 컴퓨터 아키텍쳐에 따라 미리 컴파일된 바이너리 또는 실행가능한 파일이 존재하는 디렉터리 → 해당 프로젝트 실행 시 필요한 실행파일들이 존재한다.

3. pnpm의 node_modules 구조

mkdir pnpm1 pnpm init pnpm install react cd node_modules ls -a # react, .modules.yaml, pnpm
Bash
복사
실제로 사용자가 설치한 react 패키지만 (symlink, .pnpm 디렉터리에 존재하는 패키지) 최상단에 존재한다. 이로인해… 호이트스팅이 없고..
사용자가 설치한 패키지만 존재함 -> 유령 의존성이 해결된다.
.pnpm/react@18.2.0/node_modules/react의 symlink - 아직 이해 어려우니 일단 알고만 있도록! 아래에 추가설명

node_modules tree

node_modules의 tree 스크린샷
위에 설명했듯이 node_modules의 최상단에는 사용자가 설치한 라이브러리 만 존재한다.
최상단에 존재하는 라이브러리들은 .pnpm 디렉터리에 존재하는 파일들에 대한 softlink이다. 쉽게 접근 할 수 있도록 만든 바로가기와 같이 생각하자.
“왜 하드링크 안해요? 그게 더 빠르다면서요”디렉터리는 하드링크 못한다고…!
.pnpm에 존재하는 파일들이 바로 CAS로 직접 연결된, hardlink된 파일들이다.
물론 이해가 어려울 것이다. 정작 나또한 해당 포스팅을 작성하며 “아.. 잠시만.. 그래서 뭐..?”를 외쳤으니.. → react 라이브러리를 이용한 예시를 들겠다.
graph TB
  A("node_modules/react@18.2.0")  -.symlink.-> B("node_modules/.pnpm/react@18.2.0") ==hardlink===> storage[(CAS)] 
Mermaid
복사
1.
node_modules의 최상단에 존재하는 react@18.2.0 라이브러리 디렉터리 → 해당 디렉터리는 .pnpm에 존재하는 파일에대한 symlink. 즉, 바로가기일 뿐 이다.
2.
.pnpm/react@18.2.0에 존재하는 파일들은 CAS에 존재하는 파일들에 대한 hardlink다.

4. .pnpm과 CAS를 실제로 연결시켜보기

pnpm1이라는 리액트 프로젝트에 node_modules/.pnpm/react@18.2.0의 inode를 확인하고 해당 파일이 실제 CAS에 존재하는지 확인해보자.
직접 확인해야 “아 이렇구나” 하고 넘어가는 성격이라 해본 것 뿐이다. 굳이 직접 따라하지 않아도 된다.

1. .pnpm 디렉터리에 존재하는 파일 확인하기

# .pnpm에 inode 확인 pwd # ~/pnpm1/node_modules/.pnpm cd react@18.2.0/node_modules/react
Bash
복사
node_modules 최상단에 존재하는 파일들은 전부 CAS에 softlink 되어있으니 .pnpm 디렉터리로 바로 이동하여 react@18.2.0에 node_module/react로 이동한다.

2. 해당 파일의 inode 확인하기

ls -ali index.js # 4303682 -rw-r--r-- 35 khannewayne staff 190 Aug 18 22:30 index.js
Bash
복사
hardlink는 모두가 알다시피 파일만 링크가능하다. 임의의 파일의 inode를 확인한다.

3. CAS 위치 확인하기

# CAS위치 확인 pnpm store path # ~/pnpm/store/v3 - pnpm 설치 방법마다 다름 cd ~/pnpm/store/v3/files # CAS에 실제 패키지 파일들이 설치된 위치로 이동
Bash
복사
inode를 확인했으니 CAS의 주소를 확인하고 해당 주소로 이동하여 패키지를 이루는 파일들이 저장된 디렉터리로 이동한다.

4. CAS에서 inode 검색하기

node_modules/.pnpm/react@18.2.0/node_modules/index.js는 ~/pnpm/store/v3/files/25에 난수화된 이름으로 저장되어 있다.
find . -inum 4303682 # ./25/412e88974b83582fa47ec907cb4d2a30b9027a19215609...
Bash
복사
find 명령어를 이용해 inode를 기반으로 파일을 검색한다. - HIT!
요기 잉네!
다른 프로젝트에 똑같은 react@18.2.0을 설치해도 똑같은 inode를 가지고 있는 파일들이 설치된다! → 여기서 이해가 안됐다면 글 다시 읽어보자!
.pnpm에 존재하는 모든 파일들은 CAS에서 중앙 관리된다.
프로젝트가 늘어나면 늘어날수록 용량적으로 더 효율 적인 관리가 가능하며 설치 속도는 덤! → 파일 I/O가 없잖아오!

참조