Volta vs NVM — Node.js 버전 관리 도구 비교
프로젝트에서 Git hooks를 설정하다가 이상한 문제를 만났다.
모든 검사는 로컬에서 통과하는데, git commit만 하면 exit code 3으로 실패하는 것이다.
husky - pre-commit script failed (code 3)원인을 찾아보니 NVM(Node Version Manager)이 문제였다.
더 정확히는 NVM의 동작 방식이 Git hooks의 sh -e 모드와 충돌한 것이다.
이 문제를 해결하며 Volta라는 대안을 알게 되었고, 마이그레이션 후 문제가 해결되었다. 이 글에서는 NVM과 Volta의 차이점, 각 도구의 장단점, 그리고 적합한 사용 사례를 정리한다.
NVM이란 무엇인가?
NVM(Node Version Manager)은 Node.js 버전을 관리하는 가장 유명한 도구다.
# NVM 설치
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
# Node.js 설치
nvm install 22
nvm use 22
# 프로젝트별 버전 지정
echo "22" > .nvmrc
nvm use # .nvmrc 읽어서 버전 전환NVM의 동작 방식
NVM은 쉘 함수로 구현되어 있다.
nvm use를 실행하면 현재 쉘의 PATH 환경변수를 직접 수정한다.
# nvm use 실행 전
echo $PATH
# /usr/local/bin:/usr/bin:/bin
# nvm use 22 실행 후
echo $PATH
# /Users/username/.nvm/versions/node/v22.0.0/bin:/usr/local/bin:/usr/bin:/binNVM의 장점
- 성숙한 생태계: 10년 이상 운영되며 검증된 도구
- 광범위한 호환성: Unix 계열 시스템에서 안정적으로 동작
- 단순한 설계: 쉘 함수 기반이라 동작 방식을 이해하기 쉬움
- 큰 커뮤니티: 문제 발생 시 해결 방법을 쉽게 찾을 수 있음
- 유연한 버전 선택:
nvm install node(최신),nvm install --lts(LTS) 등 다양한 옵션
NVM의 한계
- 쉘 초기화 필요:
.bashrc,.zshrc에 NVM 초기화 코드를 추가해야 함 - 쉘 시작 지연: 매번 쉘을 열 때마다 NVM을 로드하므로 느림 (0.15~0.20초)
- 환경 의존성: 현재 쉘 세션에만 영향을 미침
- 수동 전환 필요: 프로젝트마다
nvm use를 실행해야 함
Volta는 무엇이 다른가?
Volta는 Rust로 작성된 Node.js 버전 관리 도구다.
# Volta 설치
curl https://get.volta.sh | bash
# Node.js 설치
volta install node@22
volta install pnpm
# 프로젝트별 버전 고정
volta pin node@22
volta pin pnpm@10Volta의 핵심 차이점
Volta는 NVM과 근본적으로 다른 방식으로 동작한다.
1. 바이너리 심링크 + PATH 관리
Volta는 쉘 함수가 아니라 **실제 실행 파일(shim)**을 사용한다.
which node
# /Users/username/.volta/bin/node
ls -la ~/.volta/bin/node
# lrwxr-xr-x 1 username staff 34 Mar 19 00:00 /Users/username/.volta/bin/node -> ../volta~/.volta/bin을PATH에 한 번만 추가하면 끝- 쉘을 열 때마다 NVM 초기화할 필요 없음
volta라는 단일 바이너리가 모든 명령어를 가로챔
2. 프로젝트별 자동 전환
NVM과의 주요 차이점은 자동 버전 전환이다.
// package.json
{
"volta": {
"node": "22.12.0",
"pnpm": "10.32.1"
}
}프로젝트 디렉토리로 이동하면 자동으로 올바른 버전을 사용한다.
nvm use를 실행할 필요가 없다.
cd /path/to/project-with-node-22
node --version # v22.12.0 (자동 전환)
cd /path/to/another-project-with-node-20
node --version # v20.0.0 (자동 전환)3. NPM 패키지 버전 관리
Volta는 Node.js뿐만 아니라 글로벌 NPM 패키지의 버전도 관리한다.
# 프로젝트별로 다른 TypeScript 버전 사용
cd project-a
volta install typescript@4.9
tsc --version # 4.9.x
cd project-b
volta install typescript@5.0
tsc --version # 5.0.xNVM에서는 글로벌 패키지가 Node 버전과 함께 설치되므로, Node 버전을 바꾸면 글로벌 패키지를 다시 설치해야 한다.
실제로 겪은 문제 — NVM + Git Hooks
내가 겪은 문제는 이랬다:
# .husky/pre-commit
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm use 2>/dev/null
pnpm exec lint-staged
pnpm typecheck이 스크립트는 로컬에서는 잘 동작했다.
하지만 git commit을 실행하면 exit code 3으로 실패했다.
문제의 원인
Husky는 Git hooks를 sh -e 모드로 실행한다.
이 모드에서는 non-zero exit code를 반환하면 즉시 종료된다.
# NVM의 nvm use는 exit code 3을 반환
# (이미 사용 중인 버전일 때)
nvm use 2>/dev/null
echo $? # 3
# sh -e 모드에서는 이것이 에러로 취급됨
sh -e -c "nvm use 2>/dev/null; echo 'done'"
# (스크립트 즉시 종료, 'done' 출력 안 됨)nvm use가 exit code 3을 반환하는 것은 에러가 아니다.
"요청한 버전이 이미 활성화되어 있다"는 의미일 뿐이다.
하지만 sh -e는 이를 에러로 취급하고 스크립트를 중단한다.
|| true로도 해결 안 됨
처음에는 || true를 붙여봤다.
nvm use 2>/dev/null || true하지만 여전히 실패했다.
NVM 스크립트 내부 어딘가에서 exit 3을 직접 호출하기 때문이다.
Volta를 사용한 해결 방법
Git hooks에서 NVM 초기화를 완전히 제거하고 Volta를 사용하니 문제가 해결되었다.
# .husky/pre-commit (after)
pnpm exec lint-staged
pnpm typecheckVolta는 PATH에 한 번만 추가하면 되므로,
Git hooks에서 별도의 초기화가 필요 없다.
성능 비교
쉘 시작 시간
# NVM
time zsh -c "exit"
# 0.15s ~ 0.20s
# Volta
time zsh -c "exit"
# 0.03s ~ 0.05sVolta는 쉘 초기화 오버헤드가 거의 없다.
버전 전환 시간
# NVM
time nvm use 22
# 0.5s ~ 1.0s
# Volta (자동 전환)
time cd project && node --version
# 즉시 (오버헤드 없음)Volta는 디렉토리 이동만으로 버전이 전환된다.
Volta의 장점
- 빠른 성능: 쉘 초기화 오버헤드 없음 (0.03~0.05초)
- 자동 전환: 프로젝트 디렉토리 이동만으로 버전 자동 전환
- 패키지 관리: Node뿐만 아니라 pnpm, yarn 같은 도구도 관리
- 환경 안정성: Git hooks, CI 환경에서 추가 설정 불필요
- 프로젝트 격리: 글로벌 패키지도 프로젝트별로 버전 관리 가능
Volta의 한계
- 상대적으로 작은 커뮤니티: NVM 대비 사용자 수가 적어 문제 해결 사례가 제한적
- Windows 지원 미흡: Windows 네이티브 지원은 실험적 단계 (WSL은 정상 동작)
- 오래된 Node 버전 제한: 매우 오래된 레거시 버전(Node 6, 8 등) 지원 부족
- 팀 전환 비용: 기존 NVM 워크플로우를 사용하는 팀의 경우 마이그레이션 노력 필요
- 디버깅 복잡도: Shim 기반 구조로 인해 문제 발생 시 원인 파악이 어려울 수 있음
마이그레이션 가이드
1. Volta 설치
curl https://get.volta.sh | bash2. 현재 Node 버전 확인
node --version # v22.12.0
pnpm --version # 10.32.13. Volta로 동일 버전 설치
volta install node@22.12.0
volta install pnpm@10.32.14. 프로젝트에 버전 고정
cd /path/to/your/project
volta pin node@22.12.0
volta pin pnpm@10.32.1이 명령은 package.json에 자동으로 추가한다:
{
"volta": {
"node": "22.12.0",
"pnpm": "10.32.1"
}
}5. .nvmrc 제거 (선택)
Volta를 팀 표준으로 정했다면:
rm .nvmrc
git add .nvmrc package.json
git commit -m "chore: migrate from NVM to Volta"NVM 사용자와 공존하려면 둘 다 유지해도 된다.
6. Git hooks 정리
# .husky/pre-commit, .husky/pre-push에서
# NVM 초기화 코드 제거
# Before
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm use 2>/dev/null
pnpm lint
# After
pnpm lint # Volta가 자동으로 올바른 버전 사용비교 요약
| 항목 | NVM | Volta |
|---|---|---|
| 성능 | 느림 (쉘 초기화 0.15~0.20초) | 빠름 (쉘 초기화 0.03~0.05초) |
| 자동 전환 | ❌ (수동으로 nvm use 필요) | ✅ (디렉토리 이동 시 자동) |
| 커뮤니티 | ✅ 매우 큼 (10년+ 운영) | ⚠️ 상대적으로 작음 |
| Windows 지원 | ⚠️ nvm-windows 별도 도구 | ⚠️ 실험적 (WSL은 정상) |
| 패키지 관리 | ❌ (Node 버전별로 재설치) | ✅ (프로젝트별 격리) |
| Git Hooks 호환 | ⚠️ 추가 설정 필요, 이슈 가능성 | ✅ 추가 설정 불필요 |
| 레거시 버전 | ✅ Node 0.x부터 지원 | ⚠️ 오래된 버전 제한적 |
| 학습 곡선 | ✅ 단순한 쉘 함수 | ⚠️ Shim 구조 이해 필요 |
어떤 도구를 선택할까?
NVM이 적합한 경우
-
Windows 네이티브 환경 WSL 없이 Windows에서 직접 사용해야 하는 경우
-
레거시 프로젝트 유지보수 Node 6, 8 같은 매우 오래된 버전이 필요한 경우
-
기존 팀 워크플로우 팀 전체가 NVM을 사용 중이고 전환 비용이 큰 경우
-
검증된 안정성 우선 오랜 기간 검증된 도구를 선호하는 보수적인 환경
Volta가 적합한 경우
-
새 프로젝트 시작 처음부터 효율적인 워크플로우를 구축하고 싶은 경우
-
여러 프로젝트 작업 프로젝트 간 빈번한 전환이 필요한 경우
-
CI/CD 환경 최적화 Git hooks, CI 파이프라인에서 안정적인 동작이 중요한 경우
-
패키지 관리 복잡도 글로벌 패키지를 프로젝트별로 관리해야 하는 경우
-
성능 민감도 쉘 시작 시간이나 전환 속도가 중요한 경우
결론
NVM과 Volta는 같은 문제를 해결하지만 근본적으로 다른 접근법을 사용한다.
NVM은 10년 이상 검증된 안정성과 큰 커뮤니티를 가진 표준적인 선택이다. 반면 Volta는 자동 전환과 성능 최적화로 현대적인 워크플로우를 제공한다.
내가 겪은 경험
Git hooks에서 발생한 NVM의 exit code 이슈는 쉘 함수 기반 설계의 한계를 보여줬다. Volta로 전환 후 추가 설정 없이 문제가 해결되었고, 프로젝트 간 전환도 자동화되었다.
하지만 이것이 모든 상황에서 Volta가 정답이라는 의미는 아니다. 팀의 기존 워크플로우, Windows 환경 지원, 레거시 버전 필요 등 각자의 상황에 따라 적합한 도구는 다를 수 있다.
선택 기준
- 안정성과 검증된 도구가 중요하다면 → NVM
- 효율성과 자동화가 중요하다면 → Volta
- Windows 네이티브가 필요하다면 → NVM
- 여러 프로젝트를 자주 전환한다면 → Volta
- 레거시 Node 버전이 필요하다면 → NVM
- CI/CD 환경 최적화가 중요하다면 → Volta
둘 다 훌륭한 도구다. 자신의 상황에 맞는 선택을 하면 된다.