notes
nvm
nvm으로 Node.js 버전 설치·전환·프로젝트별 관리하는 방법.
- nvm은 Node 여러 버전을 깔아 두고
nvm use로 바꿔 끼는 도구다. - 프로젝트 루트의
.nvmrc에 버전을 적어 두면nvm use한 번으로 맞춰진다. - CI에서는
setup-node의node-version-file로 같은.nvmrc를 읽게 한다.
왜 쓰나
Node는 버전마다 동작이 조금씩 다르다. 회사 일이랑 개인 프로젝트를 같이 하다 보면 요구하는 버전이 꼭 갈린다.
nvm 없이 Node를 직접 깔아 쓰면 버전 바꿀 때마다 지웠다 깔았다 해야 한다. nvm을 쓰고 나서는 그게 명령어 한 줄이 됐다.
원리는 단순하다. 버전마다 ~/.nvm/versions/node/v20.x.x 같은 폴더에 따로 깔아 두고, nvm use를 하면 PATH 맨 앞을 그 버전의 bin 폴더로 바꿔 끼운다. 그래서 which node를 찍어 보면 경로가 ~/.nvm/versions/...로 나온다. 시스템에 깔린 Node는 건드리지 않는다.
비유
자주 쓰는 명령어
# 설치 가능한 버전 목록
nvm ls-remote
# 특정 버전 설치
nvm install 20
nvm install 18.19.0
# 지금 터미널에서 쓸 버전
nvm use 20
# 기본 버전 (새 터미널 열 때)
nvm alias default 20
# 설치된 버전 목록
nvm ls
# 현재 버전
node -v
.nvmrc — 프로젝트마다 버전 고정
프로젝트 루트에 .nvmrc 파일:
20
그 디렉터리에서:
nvm use # .nvmrc 읽어서 자동 전환
팀원 모두 같은 Node 버전으로 맞출 때 쓴다. 숫자 말고 lts/*나 lts/iron 같은 별칭도 넣을 수 있다.
.nvmrc에 적힌 버전이 아직 안 깔려 있으면 nvm use는 에러를 내고 끝난다. 그때는 nvm install을 인자 없이 치면 .nvmrc를 읽어서 깔아 준다.
매번 nvm use 치기 귀찮아서 ~/.zshrc에 넣어 둔 훅이다. cd할 때마다 .nvmrc를 찾아서 버전을 맞추고, 없는 폴더로 나가면 default로 돌린다.
autoload -U add-zsh-hook
load-nvmrc() {
local nvmrc_path
nvmrc_path="$(nvm_find_nvmrc)"
if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version
nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")
if [ "$nvmrc_node_version" = "N/A" ]; then
nvm install
elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then
nvm use
fi
elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then
nvm use default
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrcnvm vs npm vs pnpm (헷갈리기 쉬움)
nvm → Node 20 선택
└→ pnpm install → node_modules 설치
macOS에서 설치 (요약)
공식 설치 스크립트 또는 Homebrew:
# curl 방식 (nvm 공식)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
# 셸 설정 후
nvm install 20
nvm use 20
설치 스크립트가 ~/.zshrc에 아래 로딩 코드를 넣어 준다. 터미널을 새로 열었는데 nvm: command not found가 뜨면 대부분 이 줄이 빠졌거나 다른 rc 파일에 들어간 경우였다.
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
Homebrew로 깐 경우는 경로가 /opt/homebrew/opt/nvm/nvm.sh로 바뀐다. 다만 nvm 쪽에서 brew 설치는 공식 지원하지 않는다고 해서, 나는 curl 방식으로 깐다.
fnm / volta — nvm 대안
셋 다 하는 일은 같다. Node 버전 스위처다. 나는 익숙해서 nvm을 계속 쓰는데, 셸 시작이 느리다 싶으면 fnm으로 갈아타는 것도 괜찮다.
실무 팁
- 모노레포는 루트
.nvmrc+enginesinpackage.json으로 버전 맞추기 nvm use안 하고 빌드 깨지면 →node -v먼저 확인- global 패키지는 Node 버전마다 따로 설치됨 (
npm i -g한 번 더) - CI(GitHub Actions)는 nvm 대신
actions/setup-node로 같은 버전 지정 - 새 버전으로 올릴 때 전역 패키지까지 옮기려면
nvm install 22 --reinstall-packages-from=20
CI에서도 같은 버전 쓰기
CI 러너에는 nvm이 없으니 setup-node가 .nvmrc를 직접 읽게 한다. 이렇게 해 두면 버전을 올릴 때 .nvmrc 한 군데만 고치면 로컬, 팀원, CI가 같이 따라온다.
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- run: node -v
package.json의 engines에도 "node": ">=20"처럼 적어 두면, 다른 버전으로 설치할 때 경고가 떠서 한 번 더 걸러진다.
요약
nvm은 Node 여러 버전을 깔아 두고 nvm use로 갈아 끼는 도구다. 프로젝트마다 Node 버전이 다르면 사실상 없으면 안 되는 도구라서, 새 맥을 세팅하면 제일 먼저 깐다.