오늘은 개발환경에서 여러개의 node version 을 관리하는 몇 가지 방법 중 nodenv 에 대해 알아볼까 합니다.
프로젝트가 많아지고 node 의 경우 버전의 개선이 빠르고 연관되는 lib 들도 모두 node version 에 종속되기 때문에 프로젝트들 마다 최적화된 node version 을 각각 유지할 수 밖에 없습니다.
여러 node version 을 관리하는 기법으로는 nvm, n!, nodenv 등이 있구요. 한국에서 가장 많이 사용되는 것은 아마도 nvm 이 아닐까 합니다. 처음 소개되고 널리 알려진 것이 아마도 nvm 이기 때문이지 않을까요? 한국은 무엇이든 선점효과가 좀 많이 큰 편인듯이요.
하지만 제가 오늘 소개할 방법은 nvm 이 아닌 nodenv 입니다. 제가 nodenv 를 선호하는 이유는 pyenv, rbenv 처럼 node 가 아닌 다른 언어에 대한 개발환경도 동일한 방식으로 여러 개의 version 들을 관리할 수 있기 때문입니다. 효율(속도)보다는 관리 포인트가 적어지는 것을 선호하는 중년 개발자의 특성이라고 해두죠. python 이나 ruby 등도 두루두루 하다보니..
본 포스트에서는 nodenv 를 통해 node version 관리를 해 보도록 하겠습니다.
작동방식
nodenv 는 OS 가 입력된 명령어를 찾아서 실행하는 과정에 개입하여 작동되는 방식을 취합니다.
PATH 환경변수로 지정된 값을 Intercept 하는 방식이죠.
PATH 환경변수
node 나 npm 같은 특정 명령어가 요청되면, OS 는 해당 명령어를 찾기 시작합니다.
해당 명령어를 찾아야 실행할 수가 있으니까요. 이때 OS 가 참조하는 경로가 PATH 로 지정된 경로들 입니다.
PATH 로 지정된 경로를 순서대로 탐색해서 그 중 가장 먼저 발견된 해당 명령어를 OS 는 실행하게 되는거구요.
PATH 환경변수는 일반적으로 아래와 같은 형식을 취합니다. (Unix 계열)
/usr/local/bin:/usr/bin:/bin
탐색의 순서는 왼쪽에서 오른쪽의 순으로 진행되기 때문에 동일한 명령어가 복수의 경로에 있는 경우라도 먼저 검색된, 즉 보다 왼쪽에 있는 경로상의 명령어가 실행이 되게 됩니다.
Shims 이해하기
본래 shim 이란 특별한 이유로 두 물체사이에 일정한 간격을 의도적으로 만들고자 할 때 사용하는 일종의 끼움쇠를 뜻하지만, 컴퓨터에서는 'small library that transparently intercepts API ' 의 뜻을 갖습니다.
즉, API 중간을 가로채서 처리하기 위한 작은 라이브러리라고 할 수 있습니다 nodenv 는 바로 이 shims 를 PATH 에 삽입해서 node 실행 명령요청을 가로채는 방식으로 동작합니다.
~/.nodenv/shims:/usr/local/bin:/usr/bin:/bin
nodenv 의 shims 를 PATH 의 가장 왼쪽에 배치해서 shims 에서 처리가능한 명령어들은 이후 PATH 로 넘어가지 않고 처리해 버리도록 intercept 를 하는 방식입니다.
Shims 는 아주 간단한 방식으로 사용자가 입력한 명령어들을 가로채서 실제 실행 대상 명령어를 변경시켜서 처리할 수 있도록 해 줍니다.
사용자가 npm 명령어를 입력한 경우를 예를 들어 다시한번 동작 순서를 요약하자면
- 환경변수로 등록된 PATH 경로상에서 npm 실행 파일을 찾습니다.
- npm 이름을 가진 shim 이 검색됩니다.
- 검색된 shim(npm 이름이지요) 을 실행하고, 실행된 shim 은 nodenv 에 실행 요청을 전달합니다.
- nodenv 는 사용자가 미리 지정한 특정 node version 의 실제 npm 을 찾아 실행합니다.
Node 버전 선택
shim 이 실행되면, nodenv 는 실제로 실행한 node version 을 판단하게 되는데, 아래와 같은 순서로 실행대상 버전을 판단하게 됩니다.
- NODENV_VERSION 이 지정된 경우 해당 버전을 실행.
NODENV_VERSION 이 환경변수로 지정되어 있을 경우, nodenv 는 가장 우선해서 해당 version 의 node 를 실행합니다.
이를 이용해서 빌드, CI 작업시에 프로젝트에 해당하는 특정 node 환경을 유지 관리 할 수 있습니다. (build from isolated env)
- 가장 먼저 발견된 .node-version 파일에 지정된 해당 버전을 실행.
nodenv 는 사용자가 명령어를 입력한 경로에서 부터 root 경로까지 순차적으로 .node-version 검색하게 되며, 가장 먼저 발견된 .node-version 파일에 지정된 해당 version 의 node 를 실행합니다.
따라서 현재 작업경로(프로젝트 경로) 상에 .node-version 파일을 생성하고 필요시에는 해당 파일 내용을 변경함으로써 node version 에 대한 관리를 할 수 있습니다.
.node-version 파일은 nodenv local 명령어를 통해 어느 작업 경로에서든 생성할 수 있습니다.
- ~/.nodenv/version 파일에 지정된 특정 version 의 node 를 실행합니다.
사용자의 홈 경로의 .nodenv 경로상에 있는 version 파일을 최종적으로 실행하게 됩니다. 환경변수 또는 local 에 지정된 버전이 없을 경우 최종 실행되게 되는 version (globally 라고 하죠) 이 됩니다.
사용자 홈 경로의 version 파일은 nodenv global 명령어를 통해 작성 및 편집할 수 있습니다.
- 최종적으로 시스템에 설치된 version 의 node 를 실행합니다.
위의 모든 과정을 통해서 version 지정정보를 확인하지 못하면, nodenv 이후에 PATH 중에서 찾아지는 시스템에 설치된 version 의 node 가 실행이 되게 됩니다.
Node 설치 위치
nodenv 가 실행 대상 version 을 정하게 되면, 사용자가 실행 어플리케이션에서 지정한 모든 명령행 Parameter 정보들을 해당 버전의 node 에 전달하여 실제 node process 가 해당 parameter 를 가지고 실행되게 됩니다.
특정 버전의 node 들은 모두 본인의 경로를 갖고, 해당 경로는 사용자 홈 경로의 .nodenv/versions 하위에 위치 하게 됩니다.
~/.nodenv/versions/0.10.36/
~/.nodenv/versions/0.12.0/
~/.nodenv/versions/iojs-1.0.0/
nodenv 를 통해 설치된 버전목록을 조회할 때 출력되는 버전 정보와 해당 경로 정보는 정확히 일치하므로 어렵지 않게 특정 node 의 실제 설치 위치를 식별 할 수 있습니다.
Installation
자 그럼 설치를 해 볼까요?
GitHub 에서 땡겨오는 방법
nodenv 도 오픈소스 이기 때문에 어렵지 않게 GitHub 에서 가져다 쓸 수 있습니다. 물론 직접 프로젝트에 기여하셔도 되구요.
git 명령어가 낯설다면, 차차 git 에 대한 포스트로 올릴 예정이니 참조하시구요.
$ git clone https://github.com/nodenv/nodenv.git ~/.nodenv
git clone 명령어로 내 홈 경로의 .nodenv 경로로 소스를 당겨왔습니다.
설치된 nodenv 의 bin 경로를 내 PC 의 PATH 경로에 추가해 줍니다.
$ echo 'export PATH="$HOME/.nodenv/bin:$PATH"' >> ~/.bash_profile
사용하시는 OS 기준으로 .bash_profile 대신 다신 파일을 지정하셔야 할 수도 있습니다.
저는 zsh 를 사용하기 때문에 아래와 같이 했습니다.
$ echo 'export PATH="$HOME/.nodenv/bin:$PATH"' >> ~/.zshrc
Ubuntu 를 쓰시는 경우에는 아래와 같이 ..
$ echo 'export PATH="$HOME/.nodenv/bin:$PATH"' >> ~/.bashrc
환경변수를 변경하였으니 shell session 을 다시 닫고 열어주셔야 겠죠? exit & open shell.
위와 같이 nodevn 경로가 PATH 에 추가되었네요.
이제 nodenv init 을 실행합니다. 초기 환경 설정을 위해서이구요.
아래와 같이 현재 제가 사용하는 쉘에 맞게 설정 안내가 출력되구요.
해당 내용을 쉘 설정 파일에 추가해 주시면 됩니다.
추가 한 후에 설정 파일 확인!
제 환경에서는 위와 같이 eval "$(nodenv init -)" 를 추가하였습니다.
당연히 다시 한번 쉘을 재실행해 주셔야 nodenv 가 적용되겠죠? 다시한번 쉘 재시작. exit & run shell
설치 확인 및 설정
설치가 완료 되었으니 쉘에서 아래 명령어를 실행해보면,
$ type nodenv
위와 같이 설치 및 설정이 완료된 제 장비 상에서는 정상적으로 nodenv 함수를 인지하고 있습니다.
Homebrew 를 이용해서 Mac 에 설치하기
Mac 에서는 어렵게 GubHub 에서 checkout 않고 brew 를 이용해서 손쉽게 설치할 수 있습니다.
(brew 에 대해서 처음 들으셨다구요? 직접 검색해 보시기 바랍니다. 이미 본 포스트가 너무 길어졌네요. ㅠㅠ, Mac 을 위한 프로그램 매니저 입니다. 편리한.)
brew 가 설치되어 있고 사용하실 줄 아시면 아래 명령어를 통해 간단히 설치하시면 됩니다.
$ brew update
$ brew install nodenv
$ nodenv init
설치가 완료! 간단하죠? 저는 github 으로 이미 설치가 되어서 brew 를 통한 설치는 진행하지는 않았습니다. 그래서 스샷은 생략합니다.
사용법
nodenv 설치를 마쳤으니 사용할 node version 을 추가하고 설정을 해야 프로젝트에서 실제 사용이 가능하겠지요?
nodenv 에 대한 사용법은 다음 포스트를 참조하세요. http://dreamholic.tistory.com/108
nodenv 삭제하기
더 이상 필요없어진 nodenv 를 삭제하는 법도 아셔야 겠죠? 언젠가는 지워야 할 날도 오니까요.
nodenv 는 완전히 삭제를 하거나 또는 일시적으로 사용불가 하게 설정하거나 두 가지 방식을 적용할 수 있습니다.
일시적으로 사용 불가 하게 설정하는 방법은 profle 또는 rc 파일에 추가했던 nodenv init
라인만 제거해 주는 것입니다.
이 라인을 제거하면 nodenv shims intercept
를 PATH 에서 제거하게해서 nodenv 관련 동작이 전혀 작동하지 않게 됩니다.
이 방식은 실제 설치되어 있는 모든 nodenv 및 관련 node version 들을 유지하기 때문에 필요시에 즉시 사용가능 하도록 복원할 수 있다는 장점이 있습니다.
완전히 삭제하는 방법은 우선 nodenv init
라인을 제거해 주신 후 실제 설치된 경로 전체를 삭제해 주는 것입니다.
삭제 대상 경로는 ~/.nodenv
입니다.
rm -rf ~/.nodenv
를 실행하시면 됩니다. 반드시 삭제전에 profile 또는 rc 파일에 존재하는 nodenv init
라인을 제거한 후 실행하시기 바랍니다.
폴더 및 파일은 삭제하였는데 여전히 nodenv init
라인이 작동할 경우 부팅 시 또는 쉘을 열때마다 오류 메세지를 접하게 되기 때문에 오류 메세지 보는 것을 좋아한다면 모를까 반드시 해당 라인을 제거해 주기 바랍니다.
Homebrew 를 이용한 설치 제거
brew 를 이용해 설치한 경우에는 보다 간단히 제거할 수 있습니다.
$brew uninstall nodenv
를 실행하시면 간단히 제거 됩니다.
긴 글 읽어주셔서 감사합니다.
ps. 본 포스트는 제 개인 블로그에도 함께 발행되었습니다.
http://dreamholic.tistory.com/
와 조용한곳에서 다시 잃고 실습 해봐야 겠어요
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
정성 있는 글 감사해요~
꼭 한 번 해보겠습니다
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit