이 글에서는 스낵게임 개발 중 패키지 매니저(pnpm) 버전 업데이트 과정에서 발생한 에러와 원인, 해결 과정을 다룹니다. 패키지 매니저의 lifecycle script 차단과 별도 옵션을 통한 실행 방법을 설명하고 있으며, 그 외 내용은 다루지 않습니다.
스낵게임에서는 게임용 에셋 처리와 최적화를 위해 AssetPack을 사용하고 있습니다.
AssetPack은 웹 에셋 최적화 도구로, 여러 이미지를 하나의 스프라이트로 합치거나 다양한 포맷으로 변환하는 기능을 제공합니다. 이미지를 하나의 스프라이트로 합치면 각각의 이미지마다 네트워크 요청을 보내지 않아도 된다는 장점이 있어요.

그런데 신규 기능 추가를 준비하면서 게임 에셋을 추가했더니, 스프라이트를 생성할 때 에러가 발생했습니다.

에러 메시지를 보면 Assetpack 플러그인에서 사용하는 Sharp 라이브러리 설치 과정에서 발생한 문제로 보여요.
최근 사용하지 않는 패키지를 정리하면서 패키지 매니저 버전도 pnpm@9에서 pnpm@10으로 올렸는데,
이때 패키지 설치 방식에 변화가 있었던 걸로 추정되었습니다.
pnpm의 릴리즈 노트를 확인해보니 1월에 공개된 10.0.0부터 Lifecycle script 실행에 대한 변경이 있었습니다.
릴리즈 노트 속 블로그에 따르면, 이런 변경 사항은 작년 12월에 발생한 Rspack 공급망 공격에 대한 대응이라고 해요.

❓ Lifecycle script
패키지 install/publish 명령어의 실행 전/후에 실행되는 스크립트로,
패키지 매니저별로 지원하는 종류는 공식 문서를 통해 확인할 수 있습니다. (NPM | Yarn | Pnpm)
💣 Rspack 공급망 공격
@rspack/core, @rspack/cli 패키지 설치 시 실행되는 postinstall 스크립트를 통해 암호화폐 채굴 프로그램을 다운로드하고 실행하는 코드가 유포된 사건
pnpm뿐만 아니라 Bun도 보안을 위해 기본적으로 Lifecycle script 실행을 제한하고, 명시적 허용을 위한 trustedDependencies 옵션을 제공합니다.
(대신 bun@1.0.16부터는 일부 주요 패키지에 대해 기본적으로 lifecycle script를 실행하도록 했기 때문에, 목록에 있는 라이브러리라면 따로 옵션을 명시할 필요는 없습니다)
다시 pnpm으로 돌아가서, 버전을 낮춰 v9와 v10의 설치 과정을 비교해봤습니다.
v9는 install 과정에서 라이브러리의 lifecycle script가 실행되는 모습을 볼 수 있습니다.

반면 v10에서는 lifecycle script가 실행되는 모습을 볼 수 없고, 경고 메시지가 표시됩니다.
경고 메시지의 제안에 따라 pnpm approve-builds 명령어로 lifecycle script 실행을 허용할 라이브러리를 선택해줬어요.
그러면 pnpm-workspace.yaml 파일에 아래와 같은 항목이 추가되면서
onlyBuiltDependencies:
- 허용된 라이브러리 목록
- ...

v9 install 과정에서 봤던 익숙한 스크립트 실행 문구가 출력되는 것을 확인할 수 있습니다.
이후 다시 AssetPack을 실행해보니 에러 메시지 없이 정상적으로 동작했습니다.

패키지 매니저 버전을 올리면서 주요 변경 사항에 대한 검토가 부족해서 예상치 못한 에러가 발생했는데,
앞으로는 필요한 설정 변경이 있는지 꼼꼼히 점검한 후 버전업을 진행해야겠다는 점을 다시 한 번 느꼈습니다. 🥲