[drrr] yarn berry zero install 도입 시도

rondido·2025년 1월 31일
0

projects

목록 보기
9/11

drrr은 monorepo를 도입하면서 yarn berry를 사용하게 되었습니다. monorepo를 도입하는 과정에서 yarn berry zero install과 pnp을 통해 패키지를 관리하는 것에 대해 알게 되었습니다.

yarn berry의 zero-install과 PnP를 도입하려 했으나, vitest와의 호환성 문제로 인해 최종적으로 node_modules 방식을 유지하기로 했다

yarn berry zero install

Yarn Berry(2.x,3.x)

모노레포 프론트엔드 아키텍처로 프로젝트를 세팅하는 과정에서 yarn으 도입하였고, version 1로 세팅 하는 과정에서 다양한 error 또는 version으로 인한 에러가 발생하게 되었습니다.

그래서 이로 인해 Yarn Berry에 대해 알게 되었으며, 해당 버전을 통해 초기 프로젝트를 세팅하게 되었습니다.

Yarn BerryYarn version 2 이상을 가리키는 새로운 Yarn 패키지 매니저입니다.

node_modules의 문제점

  • 의존성 탐색 알고리즘의 비효율 node.js에서 require()함수를 실행하여 모듈을 찾을 때까지 상위 node_mouldes 디렉토리를 순회한다. 이때 느린 디스크I/O 동작이 경로의 깊이만큼 발생합니다.
  • 저장 공간과 설치 시간 node_modules 디렉터리는 흔히 매우 큰 공간을 필요로 하고, 그만큼 설치에도 오랜 시간이 걸립니다.
  • 유령 의존성(phantom dependency) 의존성 중복 방지를 위해 호이스팅 기법을 이용하는데 이것은 의도치 않은 sdie effect를 발생시킴. 아래 그림에서 package-1은 B(1.0)을 설치한 적이 없지만 require(’b’)가 작동한다. require('B')를 사용하는 경우 B(1.0)을 의존하던 패키지를 제거하면 B를 찾지 못하는 오류가 발생합니다.

PnP & zero-install 등장

어떤 프로젝트를 구성하든 의존성은 결정적입니다. Berrynode_modules에 패키지 팡리을 저장하는 대신 패키지의 압축 파일을 ./yarn/cache 폴더에 수평적으로 저장하는 방식으로 위 문제를 해결하였습니다.이 방식을 YarnPnP라고 부릅니다. 압축 파일은 ZipFs를 이용하여 해당 모듈 로드가 필요할 때 메모리에서 압축을 해제하여 접근합니다.

PnP로 얻을 수 있는 것

  • 빠른 의존성 검색
    의존성이 .yarn/cache에 수평적으로 존재하므로 모든 패키지에 대한 접근 시간이 O(1)이 됩니다. 따라서 require()에 소요되는 시간이 크게 단축됩니다.

  • 빠른 설치

압축 파일 단위로 설치되기 때문에 의존성을 구성하는 파일의 수가 절대적으로 감소합니다. 여기에 zero-install 전략을 사용하면 아예 설치 과정을 생략할 수 있습니다.

  • 유령 의존성 방지

호이스팅을 사용하지 않기 때문에 의도하지 않은 의존성이 발생하지 않습니다.

zero-install

하나의 압축 파일들로 의존성을 관리하고 이 파일을 git으로 관리하면 설치 과정을 제거할 수 있는데 이와 같은 전략을 zero-install이라 합니다.

.yarnrc.yml

nodeLinker: "pnp" // pnp(default), pnpm, node_modules 중 설정 가능.

yarn berry의 기본 설정 값입니다.

.yarnrc.yml

nodeLinker: node-modules

vsc에서 zero-install를 사용하기 위해서는 아래와 같은 설정도 꼭 필요합니다.

yarn dlx @yarnpkg/sdks vscode

zero-install vs node_modules

실제 얼마나 큰 차이가 확인하기 위해 yarn 명령어를 통해 2개의 패키지 매니저 다운 시간을 측정해보았습니다.

node_modules의 경우 yarn 명령어 입력 시 zero-install보다 2~3분정도 더 걸린것을 확인할 수 있었습니다.

초기 세팅 단계에서도 2~3분이라면 프로젝트가 커짐에 따라 좀 더 많은 시간이 소요될것이라고 예상하였습니다.

PNP 적용에 있어서의 문제점

yarn berry에서 pnp를 이용해보면 예상과는 다르게 정상적으로 동작하지 않고 dependency 관련 에러가 발생합니다.

각 모듈이 pnp로 사용할 수 있으려면 pnp 방식에 맞게 의존성 관리가 strict하게 세팅되어 있어야 합니다. 그러나 모든 모듈이 pnp 형태에 맞게 호환되어 있는 상태가 아니기 때문에 pnp를 제대로 사용하기에는 아직 많은 문제가 발생합니다.

이로 인해 yarn에서도 완전히 strict한 방식 대신, pnp loose 모드를 통해 명시적으로 요구하는 dependency를 요구하지 않도록 할 수 있습니다.

.yarnrc.yml

pnpMode: loose

그러나 이는 pnp가 정상적으로 동작하는 것을 보장하지 않습니다. 따라서 웬만하면 pnp 모드를 이용하려면 strict 모드로 이용하는 것이 좋습니다.

drrr 프로젝트에서의 문제점

zero-installpnp를 이용하여 vitest global로 설정하는 도중 호환성 문제로 인해 오류가 발생했습니다.

정확하게 원인을 파악하고자 zero-install에서 node_modules로 변경하여 프로젝트를 실행한 결과 정상적으로 작동하였습니다.

이를 해결하기 위해 github issue에서 제시하는 deps.registryNoLoader를 사용하였지만 해결하지 못하였습니다.

import { defineConfig, configDefaults } from 'vitest/config';

export default defineConfig({
    test: {
        deps: {
            registerNodeLoader: true,
        },
        globals: true,
        environment: 'jsdom',
        exclude: [...configDefaults.exclude, 'service/*', 'admin/*', 'component/*'],
    },
});

zero-install을 사용함으로써 패키지를 보다 효율적으로 관리할 수 있습니다. 하지만 위에서 언급하였듯이 pnp와의 호환성이 완벽하지 못하고 프로젝트 설정에 대한 시간을 너무 많이 사용하여 pnp 대신 node_modules를 방식을 유지하기로 결정하였습니다.
새로운 기술 도입 자체보다, 프로젝트를 만들어 가는 과정에서 상황에 맞는 기술을 도입이 중요하다는 것을 알게 되었습니다.

참고한 블로그

github issue link

stackoverflow

profile
풋살을 좋아하는 프론트엔드 개발자

0개의 댓글