yarn2와 함께 PnP(Plug'n'Play)를 적용해보자. (feat. Typescript)

NB·2021년 5월 17일
28
post-thumbnail

먼저 기술적으로 적용시키기 전에 Yarn2 (Berry) 가 나온 배경부터 알아봅시다. 바로 기술적인 내용이 필요하신 분이라면 스킵해도 좋습니다.

왜 'Berry'라고 불리나요?
yarn2의 프로젝트 명이 berrry라고 합니다. 실제로 Github 레파지토리명이 berry입니다. :)



Yarn2의 배경

현재 React 또는 Vue 등의 라이브러리 또는 프레임워크로 개발하는 개발자들은 가장 많이 보는 것이 node_modules입니다. 하지만 동시에 node_modules는 Node.js 창시자인 Ryan Lienhart Dahl가 언급했던 Node.js의 디자인 설계 실수 중 하나이기도 합니다. 대체 왜 우리가 잘 사용하고 있는 것을 실수 중 하나라고 언급했던 것일까요?

기존 node_modules 방식

개발자들 사이에 유머가 바로 위 그림입니다. 위 사진과 같이 node_modules의 거대한 양 때문에, 여러가지 이슈가 생기기도 하는데, 가장 큰 예시가 비효율적인 의존성 목록 검색입니다. 실제 node_modules 폴더를 직접 확인해보면 연속적으로 또 다른 node_modules폴더가 존재하는 것을 확인할 수 있습니다. 실제로 수 백개의 패키지들이 서로 의존성을 가지고 있다면, 디렉토리 구조는 상당히 복잡해지는것은 확인해보지 않아도 알 수 있겠죠?

그렇기에 NPM 또는 Yarn1에서는 이렇게 의존성들이 트리형태로 분포해 있는 것을 호이스팅 방법을통해서 위로 끌어올립니다. JS에서 호이스팅 개념과 같습니다.

하지만, 이 방법을 사용하게 된다면 유령 의존성(Phantom dependencies) 현상이 발생하게 됩니다. 어떠한 의존성이 호이스팅을 통해서 최상단으로 선언되었다면, 실제로는 package.json에 선언되지 않은 패키지임에도 불구하고, 사용할 수 있는 것이죠. 실제로 이렇게 사용하는 것은 개발 협업간에 큰 혼란을 야기할 수가 있습니다!


Plug'n'Play (PnP) 방식

그렇기에 yarn2에서는 새로운 전략으로 이 문제를 해결하고자 하였습니다. 이 방식을 사용하면 어떠한 패키지를 설치하게 되면 더 이상 node_modules에 저장되지 않습니다. 대신 .yarn/cache 폴더에 해당 의존성의 정보가 저장되고, 아래와 같이 .pnp.js 파일에 의존성을 찾을 수 있는 정보가 기록됩니다.

["styled-components", [
  ["npm:5.3.0", {
    "packageLocation": "./.yarn/cache/styled-components-npm-5.3.0-965f77d02b-1f94f92b5d.zip/node_modules/styled-components/",
    "packageDependencies": [
      ["styled-components", "npm:5.3.0"]
    ],
    "linkType": "SOFT",
  }]
]]

또한, 이제 각 의존성은 Zip 아카이브로 관리되게 됩니다. 실제 .yarn/cache 폴더에 들어가보면, 다음과 같이 압축파일들이 존재하는 것을 확인할 수 있습니다.

이로서, .pnp.js에 명시된 정보에 따라서 각 패키지들은 동적으로 참조되게 됩니다. 해당 방식을 택함으로서 기존의 node_modules 방식 때보다 사용 용량이 획기적으로 줄게 되었습니다. 또한 기존의 트리형태의 node_modules 폴더를 순회할 필요가 없어졌기 때문에, 검색 속도도 증가하게 되었습니다.

게다가 해당 .yarn 폴더 자체를 원격 저장소에 업로드하는 Zero-Install 방식을 사용하게 되면, 우리는 더 이상 git clone을 실행한 뒤 추가 설치가 필요없이 바로 실행할 수도 있습니다! 이렇게 되면, 기존 CI 속도가 매우 빨라지게 되겠죠?

더구나 더 이상 호이스팅을 하지않음으로써 유령 의존성 문제도 근본적으로 해결된건 덤입니다.



Yarn2 적용

이제 본격적으로 환경을 구축해보겠습니다. 물론 위에서 PnP 방식을 설명하며 강조하였지만, 여전히 node_modules 방식을 사용할 수 있습니다. 이에 대해서는 아래에서 다루겠습니다.

  1. 먼저 Yarn을 설치해줍니다. 만약 이미 설치되어있다면 이 과정은 스킵하면 됩니다.
npm install -g yarn
  1. 프로젝트의 경로로 이동하여, 다음과 같이 berry 버전으로 설정합니다.
yarn set version berry
yarn -v
> 2.x.x

+ 2021.08.21
아래는 위 방법이 안 되시는 경우가 발생하여, 추가적으로 작성합니다!

yarn policies set-version
  1. 기존 관련 파일을 수정해보도록 하겠습니다.
  • .npmrc 파일을 .yarnrc.yml 으로 수정 [관련 옵션]
  • package.lock.json 파일이 존재한다면 제거
  • node_modules 폴더 제거
  • package.json 파일에 작성된 eslintConfig는 더 이상 사용되지 않습니다. .eslintrc.json 파일로 빼주세요.
  1. [선택사항] PnP 방식을 사용하지 않겠다면, .yarnrc.yml 파일에 다음 내용을 추가해주세요.
nodeLinker: node-modules

해당 옵션을 작성하면 zip 아카이브로 관리되는 것이 아닌 기존의 node_modules 방식으로 관리되게 됩니다.

  1. 설치를 진행해줍니다. 설치를 하고 4번 과정을 진행하지 않았다면, .yarn폴더가 생긴 것을 확인할 수 있습니다.
yarn install 
# 또는
yarn
  1. .gitignore 파일에 다음 내용을 중 하나를 추가해주세요.
### yarn ###
# Zero-Install을 사용하겠다면?
.yarn/*
!.yarn/cache
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Zero-Install을 사용하지 않겠다면?
.yarn/*
!.yarn/patches
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
.pnp.*

이제 정상적으로 개발을 진행할 수 있습니다!

아래 과정은 만약 타입스크립트를 추가 적용하고 싶은 분들을 대상으로 진행하는 내용입니다. 이제 @types/* 패키지들이 zip 아카이브로 관리되기 때문에 기존의 방식으로는 정상적으로 타입이 불러와지지 않을 것입니다. 그렇기에 다음과 같은 과정을 진행해주세요!

설명은 VSCode IDE 기준으로 설명되었습니다.

  1. 타입스크립트가 적용되지 않은 프로젝트라면 타입스크립트 관련 패키지를 설치해주세요.
    [ 아래는 코드 React를 사용한다는 기준으로 작성된 스크립트입니다. ]
yarn add -D typescript @types/node @types/react @types/react-dom @types/jest
  1. jsconfig.json대신 tsconfig.json으로 작성해주세요.
  1. ZipFS 확장자를 VSCode에 검색해서 설치해주세요.
  1. 해당 프로젝트 최상위 경로에서 다음을 입력합니다.
    (기존 방식이 deprecated되어, 새로운 방식으로 수정하였습니다.)
yarn dlx @yarnpkg/sdks vscode
  1. VSCode를 실행하여 Typescript 버전을 선택해주세요.
    위 사진과 같이 version-pnpify 버전을 선택해야 합니다. [작업 영역 버전 사용]

이제 정상적으로 타입이 호출되며, 개발을 진행할 수 있습니다!

몇 가지 유의사항

  1. Node를 실행시킬 때, 기존의 node로 스크립트를 시작하는 것이 아닌, yarn node로 스크립트를 실행시켜야 합니다.

  2. 만약 styled-components 패키지를 사용하고 계시다면 추가적으로 react-is 패키지를 설치해야만 정상적으로 작동하는 이슈가 있습니다.



긴 글 읽어주셔서 감사합니다.

만약 잘못된 정보 또는 궁금증이 있으시다면 언제든지 댓글로 알려주시길 바랍니다. 😀

:)


참고자료

  1. yarnpkg Document
  2. Phantom Dependency - Rush
  3. node_modules로부터 우리를 구원해 줄 Yarn Berry - TOSS tech
profile
𝙄 𝙖𝙢 𝙖 𝙛𝙧𝙤𝙣𝙩𝙚𝙣𝙙 𝙙𝙚𝙫𝙚𝙡𝙤𝙥𝙚𝙧 𝙬𝙝𝙤 𝙚𝙣𝙟𝙤𝙮𝙨 𝙙𝙚𝙫𝙚𝙡𝙤𝙥𝙢𝙚𝙣𝙩. 👋 💻

5개의 댓글

comment-user-thumbnail
2021년 8월 17일

yarn set version berry
yarn -v
을 해도 2.XX 가 나오는 게 아니라 1.22.11이 뜨네요 혹시 버전 설정에서 추가로 해줘야 하는 게 있나요?

1개의 답글
comment-user-thumbnail
2021년 12월 8일

PnP와 아직 호환이 되지 않는 프레임워크들이 있는데요, (예: React Native)
Yarn2 적용 4번 선택사항에서
.yarnrc.yml 에 nodeLinker: node-modules 를 추가하면
결국 PnP를 못 쓰는거네요..? ㅠㅠ

1개의 답글