Yarn PnP에는 무슨 일이 있었나?


약 두달 전쯤에, ESLint의 동작이 멈춘적이 있었습니다. 구글링 몇번만에 비슷한 문제를 겪고 있는 개발자들을 쉽게 찾을 수 있었는데 모두 vscode 1.90으로 업그레이드를 했고 Yarn pnp를 사용하고 있다는 공통점이 있었습니다.
eslint-prettier-plugin & synckit
eslint-prettier-plugin과 해당 플러그인에서 사용하는 synckit이 그 원인으로 지목됐습니다. 우선 eslint-prettier-plugin은 ESLint와 Prettier의 동작을 중재하는 역할을 합니다. ESLint와 Prettier는 역할이 겹치는 부분이 있기 때문에 이 플러그인은 ESLint가 Prettier 설정을 따르도록 함으로써 충돌을 방지합니다.
Synckit은 좀더 문제의 원인에 가까운데 비동기 워커 스레드를 동기화 시켜주는 역할을 합니다. eslint-prettier-plugin에서는 소스코드를 포매팅하는 워커스레드를 생성하는데, 이 워커스레드를 동기화 시키는데 Synckit을 사용하고 있습니다.
본론
VSCode가 1.90버전으로 업그레이드되면서 vscode를 구동하는 Electron이 29 버전으로 업그레이드 되었고, Electron 내부에서 사용하는 Node.js도 20버전으로 업그레이드 되었는데 여기서 마지막 퍼즐 조각인 experimental-loader에 대해서 이야기해보겠습니다.
ESM & experimental-loader
Node.js 12 버전부터 CommonJS와 ES Module 두가지 모듈 시스템을 지원하게 되면서 import 동작을 커스터마이징할 수 있는 CLI flag --experimental-loader가 추가되었습니다. (지금은 deprecated 되고 --import로 대체됨)
이 flag는 모듈 호환성을 필요로 하는 패키지나 yarn pnp 모드를 구현하는데 사용되고, synckit에도 사용됩니다. 하지만 node20에서 이전에는 없었던 버그가 발생해서 Worker thread를 생성할때 전달되는 --experimental-loader가 동작하지 않게 되었고 이게 공교롭게도 synckit에서 사용하고 있는 패턴과 정확히 일치합니다.
다시 요약해서 설명하자면 이렇게 됩니다.
- vscode가 업그레이드되면서 Electron과 Node.js 버전이 같이 업그레이드 됨
- 업그레이드된 버전의 Node.js 20은 --experimental-loader 동작에 버그가 있음
- eslint-prettier-plugin이 의존하는 synckit이 해당 버그로 인해 제대로 동작하지 못함
- eslint-prettier-plugin 오류 발생, ESLint 동작 불능
이 포스트는 다소 축약된 설명에 불과하지만 관련된 이슈나 Node.js 문서를 살펴본다면 Node.js 모듈 동작이나 module loader에 대한 이해를 높이는데 도움이 될 것이라고 생각합니다.
다음 링크를 한번 확인해보시는 것을 추천합니다.🙃
ESM loaders cannot be defined via Worker option execArgv in v20
