현재 상황은 다음과 같습니다.
1. 저는 현재 yarn-berry@3.2.2
를 쓰고 있어요.
2. 모노레포를 구현 중이며, 큰 연습용 레포 밑에 하위 레포지토리에서 모노레포를 구성 중이었어요.
3. vite
로 CRA를 하고, 이를 install
하던 중 발생한 오류입니다.
결국 명령어를 자세히 보면 알 수 있던 오류였어요.
먼저 의역해보자면...
- 너 만약 해당 디렉토리를 프로젝트 루트로 의도한 거 아니면, 여기에 있는
yarn.lock
,package.json
을 제거해!- 만약 의도한 거면 너 워크스페이스 설정해서 루트 정확히 해!
- 마지막으로 너는 의도한 거고, 현재 디렉토리를 완전히 독립된 프로젝트로 관리하고 싶던 거라면,
yarn.lock
을 새로 만들어!
였습니다.
솔직히 그냥 위의 명령대로 생성하면 되는데... 솔직히 궁금하잖아요?
도대체 왜 yarn.lock
을 새롭게 만들어야 할까요?
이유를 생각해보았어요.
이는 아무래도 설치를 할 때 기본적으로 yarn berry
는 yarn@1.x
과 다르게 동작하는 데에서 기인하는 것 같았어요. 그리고, 이 문제를 알면 제가 성장할 수 있다고 느꼈답니다.
그래서 거의 1년 만에 토스 기술 블로그를 참조하며 문제를 분석해봤어요.
그래도 원리가 납득이 안 되는 건 몇 가지 존재해서, yarn 공식문서를 참조하게 되었답니다.
그럼, 우리도 문제 해결도 좋지만, 좀 더 근본적인 동작 원리를 이해하기 위해 여행을 떠나 볼까요?
yarn@1.x
과 npm
은 기본적으로 node_modules
의 중복 설치로 인한 리소스 낭비를 최소화하기 위해 호이스팅을 지원하고 있어요.
다만 이는, 의존성 트리를 변화시키게 되는데요. 결과적으로 의존성이 없는 라이브러리도 import
할 수 있는, 유령 의존성을 갖도록 합니다.
따라서 yarn
2버전 이상에서는 이러한 의존성 관리를 완전히 변화시켰어요.
일단 블로그에 따르면 각 package.json
파일을 기반으로 의존성 트리를 생성한 후, 디스크에 별도로 node_modules
를 만든다고 합니다.
🙇🏻♂️ 왜 별도로 생성하나요?
이는 yarn 공식문서에서 답변을 찾을 수 있었는데요.
기존의 Node Resolution Algorithm
은 파일 측면에서만 의존성을 추론해냈기 때문입니다.
만약 찾을 수 없다면 상위 패키지로 올라가서, 계속해서 탐색하는 것이죠.
문제는 이 방식은 다음과 같은 5가지 문제점이 존재했다고 합니다.
방대한 양: 생성하는 작업은 설치의 약 70% 이상의 시간을 차지한다고 해요. 이때 이미 설치된 패키지조차 계속해서node_modules
가 포함하고 있는지 상위 node_modules
까지 올라가 그 차이를 비교해야 했어요.
따라서 기존 설치가 있어도 저장은 되지 않는다는 측면이 문제였죠.
최적화: 항상 파일 시스템과 현재 상태를 명시적으로 비교해야 하므로, 최적화할 만한 요소가 없었습니다.
Node 특성: 노드는 패키지에 관한 개념이 없어요! 따라서 파일이 접근해도 되는지에 대한 여부를 판단하지 못해요. 만약에 특정 의존성을 가진 파일이 이제는 패키지 저장소에서 접근이 불가능하다면? 배포를 위한 빌드가 불가능하겠죠?
런타임 시 많은 호출: Node의 알고리즘에는 각 필수적인 단일 파일들이 어디로부터 로드되어야 하는지를 확인하기 위한 호출들이 매우 많이 존재했어요. 어떻게 보면 실행시킬 때마다 계속해서 같은 반복적인 일들을 한다는 측면에서, 지속적으로 시간이 소요되는 거죠.
패키지 중복 최적화 불가: hoisting
은 분명 트리의 최적화를 사용되었고, 어느정도 효과가 있었지만 특정 패턴에서는 최적화가 불가능하다고 해요. 생각보다 디스크 사용량을 유발하기도 하고, 메모리에서 여러 번 인스턴스를 만들기도 한다네요.
공식문서 번역 힘들군요. 이 세상 번역러들에게 감사의 박수를... 👏🏻
음... 이래서 PnP
가 나왔다는 문서 설명이므로 문제에 완전히 딱 맞다!라고 설명하기는 어렵네요. 그렇지만 분명 우리가 알고 짚어 넘어갈 부분들은 존재한 것 같아요! 😉
저는 위의 내용을 보며 다음과 같이 해당 문제의 원인을 유추했어요.
PnP
는yarn berry
의 특징 중 하나이므로 해당 문제가 분명 이것과 연관이 있다.yarn berry
는 호이스팅 기반의 의존성 트리 구성을 벗어났고, 따라서 의존성 트리 관리에 엄격하다.- 의존성 트리 관리에 있어서 프로젝트의 패키지가 어디서부터 어디까지인지를 명확히 해야 한다.
따라서 위의 오류가 나온 것 같았어요.
패키지를 설치해줘야 하고,
package.json
과yarn.lock
의 상태를 비교하며 분석해야 하는데, 해당 모듈에서는yarn.lock
이 없었거든요!
이제 어느 정도 문제에 대해 납득이 갔어요. 따라서 해결을 해보기로 했죠.
결국 문제는 비교하는 데, 패키지가 어디서부터 어딘지를 명확히 못 따지는 문제에 봉착한 것이잖아요?
따라서 내가 여기서 package.json
에 명시된 의존성 그대로를 install
하겠다!라는 것을 확실히 비교하면서 생성하기 위해 해당 디렉토리에 yarn.lock
을 설치해줬어요.
touch yarn.lock
이후 실행을 해볼까요?
잘 되는군요!
아무래도 yarn berry
를 예전부터 알고 있기는 했지만 자유자재로 써먹지는 않은 터라, 많이 부족할 수는 있는 설명인 것 같아요.
그렇지만 나름대로 공식문서를 보면서 좀 더 딥하게 공부했다는 측면에서는, 만족스럽기도 합니다.
혹여나 제가 잘못 이해한 부분이 있다면 언제든지 적극적으로 알려주셔도 괜찮아요. 👋🏻
근거 있는 비판은 언제든지 환영입니다. 🥰
다들 즐거운 프로그래밍 하시길 바라며. 이상! 🌈
좋은 글 감사합니다~