Yarn vs. Pnpm 모노레포 간단 비교
실무에서 사용해보고 느낀 점
실무 프로젝트에서 Yarn classic/berry workspace, Pnpm workspace를 사용해봤고, 개인적으로 느낀 각각의 장단점을 가볍게 적어본다. 수치적으로 정확히 비교하는 글은 아니라는 거~
- 사실 구글 서치에서 내 블로그에 들어오는 검색어 1순위가
yarn berry monorepo이기도 해서, 한번더 우려먹어보려는 거~
결론부터 말하면, 지금은 왠만하면 pnpm 을 사용해서 프로젝트를 구성하고 기존 yarn으로 되어있던 모노레포 프로젝트도 pnpm으로 이전하려고 하고 있다
의존성 설치 속도
체감상
pnpm,yarn berry둘다 비슷한 듯 하고, 둘다 빠르다yarn berry는 순정 PnP 모드만 사용했을 때.yarn/cache디렉토리에 의존성들을.zip파일 형태로 저장한다.
뇌피셜인데, 우선
zip파일로 어느정도 압축이 되어있기 때문에 다운로드 용량 자체가 적어서 다운로드 시간 자체가 좀더 줄어들것 같고,npm/yarn classic처럼npm레지스트리에 있는 패키지 내부 파일들을 하나하나 다운 받는게 아니라zip파일 하나로 합쳐서 가져오기 때문에 http 요청-커넥션 프로세스도 줄어들기 때문에 좀더 빠르지 않을까 싶다zero-install설정을 하게 되면, (거창해보이지만 사실 git에 .yarn 디렉토리 저장해버리는 거) CI 환경에서yarn install을 안해도 되기 때문에(!) 짧게는 1분에서 많게는 몇분에 달하는 설치 시간을 아낄 수 있다.git으로 의존성 변경을 확인할 수도 있기 때문에, 나도 모르게 의존성이 버전업 되서 빌드 깨지는 걸 미리 막을수 있고, 여러 사람이 참여하는 프로젝트에서 버전이 꼬이는 문제도 방지할 수 있다.
yarn classic은,npm=>yarn으로 갈아타기 했을 때는 뭔가 좀 빠른듯 하고 CLI에 이모지도 있고 해서 뭔가 힙해보이는 느낌도 있어서 그런지 느리다는 느낌은 없었는데,pnpm,yarn berry를 쓰다가yarn classic을 쓰면 아직도 설치하고 있네하는 생각이 든다
호환성
yarn classic,pnpm을 쓰면서는 호환성 문제가 발생한 적은 없다yarn berry는 내가 마지막으로 썼던 작년 중반 정도까지 호환성 문제가 있어서, 설치에 실패하거나 vscode에서 패키지를 인식 못해서 ts 에러가 나는 경우가 많았다. 아직도 일부 라이브러리들은 호환성 문제가 있는 걸로 알고 있다.호환성 문제를 해결하려면 할 수도 있는데, 그 중 하나는 이전 블로그 (https://hashnode.com/post/ckyhgtckf08vw35s14ppr0fz3) 에서 썼던 거처럼 설정 파일
.yarnrc.yml에서nodeLinker를 설정해주는 방법이 있고,- 근데 이걸 하게 되면 의존성 설치하는게 두배가 된다. 이거는 아래 '디스크 사이즈'에서 알아보자
아니면
.yarnrc.ymlpackageExtensions를 활용해서 라이브러리 마다 하나하나 이건 이거고 저건 저거다 설정해주는 방법이 있다. 근데 이걸 해주는게 패키지 매니저의 역할인데, 이걸 못해서 사용자가 직접 해준다는게.. 근본적으로 틀려먹은거 아닌가 모르겠음
모노레포 툴인
turborepo는yarn berry와 호환이 안된다. 어차피 모노레포를 deep하게 쓰는게 아니라면yarn workspaces그자체도 뭐 나쁘진 않은데,turborepo의 캐싱 기능이 필요한 경우에는 좀 많이 아쉽다
디스크 사이즈
사실
node_modules나.yarn/cache,.pnpm-store디렉토리 사이즈를 정확하게 비교분석 해본 적은 없다. 그런거 재고 있을 시간도 없고.. 다만 배포할 때 도커빌드하고서du로 대충 어느정도 사이즈가 되는지 확인은 해보는 편인데, 세 패키지 매니저 모두 크게 차이는 없다
다만 위 호환성 문제에서
yarn berry를 사용할 때 패키지 인식 문제 때문에nodeLinker를 설정해서node_modules폴더를 사용하게 할 수가 있다. 그러면zip파일로 설치한걸node_modules에 한번 더 풀어서zip파일로 인식이 안되면node_modules에 있는걸 찾아서 사용하는 식이다.그러면 동일한 걸 하나는
.yarn/cache안에서zip파일로 갖고, 하나는node_modules안에서 압축해제 한걸로 갖고 있게 되는 셈이된다. 위 스크린샷에서node_modules폴더 사이즈가 무려 825메가가 나오는데,yarn berry nodeLinker를 하게 되면 의존성만 1.6기가를 사용하게 되는 거다pnpm도yarn berry와 유사하게 PnP 모드를 사용하기 때문에node_modules외에.pnpm-store에 자체적으로 패키지들을 압축/변형한 걸 사용한다.pnpm install을 할 때 우선.pnpm-store에 압축된 파일들을 다운로드하고, 여기 있는 걸node_modules에 풀어놓는 것 같다. 따라서npm/yarn classic보다는 디스크 용량을 좀더 차지할 수 있다
초기설정
npm은 Node.js를 설치하면, 왠만하면 자동으로 설치되는 거라 당연히 처음에 뭔가 해줄게 거의 없다
yarn classic도npm i -g yarn아니면corepack enable && corepack prepare yarn@latest --activate정도 yarn 자체를 설치하는 거만 하면 바로 사용할 수 있다yarn berry는yarn set version berry로yarn berry사용 설정을 해주고, 에디터에 맞는 sdk를 설치하고, 플러그인들을 설치해야 한다
zero-install같은 기능을 사용하려면.gitignore에 어떤 디렉토리를 넣을 건지도 상황에 따라 고려해야 한다pnp,zero-install을 잘 쓰면 잘 쓸 수 있을 거고, 초기 설정들을boilerplate로 만들어서 사용할 수도 있을 수 있겠지만, 아무튼 초기 설정하는데 손이 많이 간다. 귀찮다
pnpm은 모노레포를 사용한다면pnpm-workspace.yml파일을 추가해서 패키지 경로들을 지정해준다
CLI 편의성
pnpm은 npm/yarn classic을 써봤다면 거의 바로 사용할 수 있다.
의존성 설치를 할 때 npm 은
install을 사용하고, yarn은 add를 사용하는데, pnpm은 둘다 쓸수 있다. 기분 내키는대로 하면 된다모노레포에서 특정 패키지에만 해당하는 명령어를 사용할 때는
pnpm --filter='..'를 사용하면 되는데, 내부 패키지의 패키지명을 다 쓸 필요가 없어서 편하다. 예를 들어 내부 패키지명이@my-monorepo/app-a라면pnpm --filter=app-a run 어쩌구로 실행하면 된다
yarn은 classic/berry 둘다 workspaces에서 특정 패키지만 명령어를 사용할 때 해당 패키지명을 모두 써줘야 한다. 예를 들어 내부 패키지명이
@my-monorepo/app-a라면yarn workspace "@my-monorepo/app-a" run 어쩌구로 실행한다

