728x90
SMALL

node modules 속에 숨어 있는 패키지

유령 의존성이란?

개발 하다 보면, 어떤 패키지는 package.json에 명시적으로 추가한 적이 없는데도 프로젝트에 사용할 수 있는 경우가 있습니다. 또는 npm install을 했을 때 예상보다 더 많은 패키지가 설치되는 경우가 있습니다. 이런 현상을 유령 의존성이라고 부릅니다.

📌 유령 의존성이 발생하는 주요 원인

직접 설치하지 않은 패키지가, 하위 패키지를 통해 설치되면서 마치 직접 의존하는 것처럼 보이는 경우

  • 패키지 매니저에 따라 의존성 트리가 다르게 구성되는 경우

`npm install`과 `pnpm install`을 했을 때 설치된 `node_modules`의 구조 비교

=> npm은 90개의 하위 폴더, pnpm은 9개의 하위 폴더가 생김

 

📌 예제 재현


    
mkdir npm-test && cd npm-test
npm init -y
npm install react react-dom typescript eslint
mkdir pnpm-test && cd pnpm-test
npm init -y
pnpm install react react-dom typescript eslint

pnpm은 node_modules/.pnpm을 활용해 하드링크 최적화하지만, npm은 여러 위치에 중복 설치함.

테스트 결과를 보기 위해, 아래 버전으로 테스트하였습니다.

"eslint": "^8.12.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"typescript": "^4.6.3"

npm은 중복 설치가 발생할 수 있기 때문에, 프로젝트의 크기가 커지고 디스크 공간을 많이 차지할 수 있습니다.
pnpm은 하드링크를 사용하여 디스크 공간을 절약하고, 중복 설치를 방지할 수 있습니다.

유령 의존성이 왜 문제인가?

유령 의존성이 하위 패키지를 설치하면서 생긴 의존성이라고 제대로 관리하지 않으면 다음과 같은 에러가 발생할 수도 있습니다.

  1. 빌드 실패 및 런타임 오류 발생
    개발 환경에서는 유령 의존성이 있어서 잘 실행되지만, 배포 후에는 해당 패키지가 없어서 빌드가 실패할 수 있습니다.
  2. 의존성 관리 어려움
    특정 패키지가 어디서 온 건지 추적하기 어려워지고, 예상하지 못한 버전 충돌이 발생할 수도 있습니다.
  3. 보안 문제
    패키지 관리가 제대로 되지 않으면, 의도하지 않은 패키지가 포함될 수도 있습니다.
    직접 설치하지 않은 패키지가 하위 의존성을 통해 포함된 사례

어떻게 발견할 수 있을까?

유령 의존성을 확인하는 방법에는 여러 가지가 있습니다.

  1. npm ls 명령어 활용
    
        
    npm ls package-name
    이 명령어를 실행하면 특정 패키지가 어디서 의존하고 있는지 트리 형태로 보여줍니다.
  2. npm dedupe 명령어 활용
    
        
    npm dedupe
    이 명령어를 실행하면 중복된 의존성을 정리해 깔끔한 상태로 정리할 수 있습니다.

의존성을 해결하는 방법

명시적으로 package.json에 추가하기, lock file 삭제후 재설치, npm audit으로 보안 이슈가 있는 의존성을 포함한 패키지를 확인하기 등의 방법이 있을 것 같습니다

유령 의존성 예방하기

  1. PR 리뷰 시 lock file이 변경되었을 경우 원인을 체크하고 변경점이 진짜 필요한 내용만 변경되었는지 확인하기
  2. npm dedupe 또는 npm prune을 사용해 불필요한 패키지를 제거하는 습관을 들이기

결론

유령 의존성은 우리가 직접 설치하지 않았지만 하위 패키지를 통해 설치되면서 마치 직접적인 의존성처럼 보이는 패키지들을 의미합니다. 이를 방치하면 빌드 실패, 디버깅 난이도 증가, 보안 취약점 유발 등의 문제가 발생할 수 있습니다.
유령 의존성 문제를 사전에 예방하고 관리하면 프로젝트의 안정성과 유지보수성을 크게 높일 수 있습니다. 🚀

끄적끄적 개발자