[Yarn] Yarn-berry PnP 동작 원리 + <PATH> isn't intended to be a project error in yarn-berry issue

young_pallete·2022년 7월 31일
2

package-manager

목록 보기
1/1

🔥 문제

현재 상황은 다음과 같습니다.
1. 저는 현재 yarn-berry@3.2.2를 쓰고 있어요.
2. 모노레포를 구현 중이며, 큰 연습용 레포 밑에 하위 레포지토리에서 모노레포를 구성 중이었어요.
3. vite로 CRA를 하고, 이를 install 하던 중 발생한 오류입니다.

🙇🏻‍♂️ 해결

결국 명령어를 자세히 보면 알 수 있던 오류였어요.

먼저 의역해보자면...

  1. 너 만약 해당 디렉토리를 프로젝트 루트로 의도한 거 아니면, 여기에 있는 yarn.lock, package.json을 제거해!
  2. 만약 의도한 거면 너 워크스페이스 설정해서 루트 정확히 해!
  3. 마지막으로 너는 의도한 거고, 현재 디렉토리를 완전히 독립된 프로젝트로 관리하고 싶던 거라면, yarn.lock을 새로 만들어!

였습니다.

솔직히 그냥 위의 명령대로 생성하면 되는데... 솔직히 궁금하잖아요?
도대체 왜 yarn.lock을 새롭게 만들어야 할까요?

이유를 생각해보았어요.
이는 아무래도 설치를 할 때 기본적으로 yarn berryyarn@1.x과 다르게 동작하는 데에서 기인하는 것 같았어요. 그리고, 이 문제를 알면 제가 성장할 수 있다고 느꼈답니다.

🔍 문제 탐색

그래서 거의 1년 만에 토스 기술 블로그를 참조하며 문제를 분석해봤어요.
그래도 원리가 납득이 안 되는 건 몇 가지 존재해서, yarn 공식문서를 참조하게 되었답니다.

그럼, 우리도 문제 해결도 좋지만, 좀 더 근본적인 동작 원리를 이해하기 위해 여행을 떠나 볼까요?
yarn@1.xnpm은 기본적으로 node_modules의 중복 설치로 인한 리소스 낭비를 최소화하기 위해 호이스팅을 지원하고 있어요.

다만 이는, 의존성 트리를 변화시키게 되는데요. 결과적으로 의존성이 없는 라이브러리도 import할 수 있는, 유령 의존성을 갖도록 합니다.

따라서 yarn 2버전 이상에서는 이러한 의존성 관리를 완전히 변화시켰어요.
일단 블로그에 따르면 각 package.json 파일을 기반으로 의존성 트리를 생성한 후, 디스크에 별도로 node_modules를 만든다고 합니다.

🙇🏻‍♂️ 왜 별도로 생성하나요?

이는 yarn 공식문서에서 답변을 찾을 수 있었는데요.
기존의 Node Resolution Algorithm은 파일 측면에서만 의존성을 추론해냈기 때문입니다.
만약 찾을 수 없다면 상위 패키지로 올라가서, 계속해서 탐색하는 것이죠.

문제는 이 방식은 다음과 같은 5가지 문제점이 존재했다고 합니다.

  • 방대한 양: 생성하는 작업은 설치의 약 70% 이상의 시간을 차지한다고 해요. 이때 이미 설치된 패키지조차 계속해서node_modules가 포함하고 있는지 상위 node_modules까지 올라가 그 차이를 비교해야 했어요.
    따라서 기존 설치가 있어도 저장은 되지 않는다는 측면이 문제였죠.

  • 최적화: 항상 파일 시스템과 현재 상태를 명시적으로 비교해야 하므로, 최적화할 만한 요소가 없었습니다.

  • Node 특성: 노드는 패키지에 관한 개념이 없어요! 따라서 파일이 접근해도 되는지에 대한 여부를 판단하지 못해요. 만약에 특정 의존성을 가진 파일이 이제는 패키지 저장소에서 접근이 불가능하다면? 배포를 위한 빌드가 불가능하겠죠?

  • 런타임 시 많은 호출: Node의 알고리즘에는 각 필수적인 단일 파일들이 어디로부터 로드되어야 하는지를 확인하기 위한 호출들이 매우 많이 존재했어요. 어떻게 보면 실행시킬 때마다 계속해서 같은 반복적인 일들을 한다는 측면에서, 지속적으로 시간이 소요되는 거죠.

  • 패키지 중복 최적화 불가: hoisting은 분명 트리의 최적화를 사용되었고, 어느정도 효과가 있었지만 특정 패턴에서는 최적화가 불가능하다고 해요. 생각보다 디스크 사용량을 유발하기도 하고, 메모리에서 여러 번 인스턴스를 만들기도 한다네요.

공식문서 번역 힘들군요. 이 세상 번역러들에게 감사의 박수를... 👏🏻

✅ 정리

음... 이래서 PnP가 나왔다는 문서 설명이므로 문제에 완전히 딱 맞다!라고 설명하기는 어렵네요. 그렇지만 분명 우리가 알고 짚어 넘어갈 부분들은 존재한 것 같아요! 😉

저는 위의 내용을 보며 다음과 같이 해당 문제의 원인을 유추했어요.

  • PnPyarn berry의 특징 중 하나이므로 해당 문제가 분명 이것과 연관이 있다.
  • yarn berry는 호이스팅 기반의 의존성 트리 구성을 벗어났고, 따라서 의존성 트리 관리에 엄격하다.
  • 의존성 트리 관리에 있어서 프로젝트의 패키지가 어디서부터 어디까지인지를 명확히 해야 한다.

따라서 위의 오류가 나온 것 같았어요.

패키지를 설치해줘야 하고, package.jsonyarn.lock의 상태를 비교하며 분석해야 하는데, 해당 모듈에서는 yarn.lock이 없었거든요!

해결 방법을 원한다면 🚀

이제 어느 정도 문제에 대해 납득이 갔어요. 따라서 해결을 해보기로 했죠.
결국 문제는 비교하는 데, 패키지가 어디서부터 어딘지를 명확히 못 따지는 문제에 봉착한 것이잖아요?

따라서 내가 여기서 package.json에 명시된 의존성 그대로를 install 하겠다!라는 것을 확실히 비교하면서 생성하기 위해 해당 디렉토리에 yarn.lock을 설치해줬어요.

touch yarn.lock

이후 실행을 해볼까요?

잘 되는군요!

🌈 마치며

아무래도 yarn berry를 예전부터 알고 있기는 했지만 자유자재로 써먹지는 않은 터라, 많이 부족할 수는 있는 설명인 것 같아요.
그렇지만 나름대로 공식문서를 보면서 좀 더 딥하게 공부했다는 측면에서는, 만족스럽기도 합니다.

혹여나 제가 잘못 이해한 부분이 있다면 언제든지 적극적으로 알려주셔도 괜찮아요. 👋🏻
근거 있는 비판은 언제든지 환영입니다. 🥰

다들 즐거운 프로그래밍 하시길 바라며. 이상! 🌈

profile
People are scared of falling to the bottom but born from there. What they've lost is nth. 😉

1개의 댓글

comment-user-thumbnail
2024년 5월 9일

좋은 글 감사합니다~

답글 달기