본문 바로가기

카테고리 없음

node 프로젝트의 플래그 변수로 NODE_ENV를 쓰지 않는 걸 추천함

원래 나는 사내 node 프로젝트에서 로컬 환경 실행이나 사내 서버, 운영 서버 등 서로 다른 환경에서 실행하기 위해 NODE_ENV를 플래그 변수로 사용했다.

  • 로컬 환경이라면 NODE_ENV='local'
  • 사내 테스트 서버라면 NODE_ENV='development'
  • 운영 서버라면 NODE_ENV='production' 을 주는 방식이다.

그러던 중 프로젝트를 모노 레포로 전환하며 관리 도구로 lerna를 사용했고, 이 과정에서 NODE_ENV 가 문제가 되어 더 이상 노드 런타임 실행의 분기처리에 이 변수를 사용하지 않으려 한다.

 

1. lerna가 무엇인가?


lerna는 모노 레포 프로젝트의 관리 도구이다.

모노 레포 프로젝트란 독립적으로 패키지 관리, 빌드 및 실행되는 프로젝트를 하나의 레포지토리로 통합한 것이다. 기존에는 독립적인 프로젝트 A,B,C가 각각의 package.json 과 webpack 설정을 가지고 별도로 CI/CD를 올리던 상황이었는데, 이들을 하나로 통합해서 관리하는 컨테이너 프로젝트 X로 만들었다.

lerna는 이들을 통합적으로 실행하고 관리할 수 있게 도와준다.

 

내 설정은 X에 package.json 내 workspace로 A,B,C를 등록한다.

그리고 lerna를 설치한 후, lerna 스크립트로 이들을 시작하도록 했다.

 

아래 스크립트를 실행하면 

lerna run start

하위 프로젝트 A,B,C에서 `npm run start`가 실행된다.

 

2. 문제가 무엇이었는가?


npm run start는 로컬 환경에서 실행을 위한 커맨드다. 따라서 하위 프로젝트의 NODE_ENV는 `local`로 설정되어야 했다.

하지만 lerna로 이들을 실행하면 NODE_ENV는 `development`로 설정되었다.

 

3. 원인이 무엇이었는가?


  • 여기서 NODE_ENV라는 건 node 런타임 실행 시 프로세스에서 process.env에 등록되는 프로퍼티중 하나다. nodejs는 이 변수 자체를 특별히 예약하거나 특정한 값으로 강제하지 않는다.
  • 하지만 Express, React, Webpack, Babel, Vue CLI 등 수많은 JS 도구들이 “실행 모드 구분”의 사실상 표준 변수로 NODE_ENV를 채택하고 사용한다.
    • 예컨대, Webpack은 cli나 설정 파일(webpack.config.js)에서 mode 프로퍼티를 `development`로 설정하면 NODE_ENV도 해당 값으로 변경된다. `production`으로 설정해도 마찬가지다.
  • lerna는 nx를 기반으로 작동한다. 이들은 특정 커맨드(start, build...)를 사용할 때, 실행 모드 구분을 위해 자동으로 NODE_ENV를 특정 값으로 세팅했다.
  • 내 프로젝트는 로컬 환경 실행 시 NODE_ENV를 cli 단계에서 설정하지 않는다. 대신, .env 파일을 로드하여 빌드 마지막 시점에 런타임에 주입하였다.
    • NODE_ENV를 특정 값으로 cli 단계에 설정하는 건 development, productuon을 세팅하는 경우에만 이었다.
  • 따라서, 로컬 실행단계에서 원래는 undefined이었어야할 NODE_ENV가 lerna로 인해 development로 설정되며 문제가 생겼던 것이다.

 

4. 대안은 무엇인가? 앞으로는 어떻게 할 것인가?


프레임워크나 cli 도구(lerna, webpack...)에서 표준 실행 플래그 변수로 NODE_ENV를 사용하므로 프로젝트의 실행 플래그 변수는 별도로 사용하는 것이 좋고, 해당 변수를 CLI 로 빌드 커맨드 실행 시점에 삽입해야 한다.

이건 두 가지 방법이 있다.

 

4.1. 번들러의 환경 변수 주입 명령어 사용(webpack)

webpack cli는 `--env` 옵션으로 전달된 값을 webpack 설정 파일의 `env`객체로 받아서 자유롭게 활용할 수 있다.

 

예시

아래의 커맨드처럼 --env로 `deployEnv`라는 환경변수를 설정한다.

    # package.json
  
    "start": "webpack serve --open --mode development --env deployEnv=local",

 

그러면 webpack.config.js에서 env 객체로 활용 가능하다.

// @webpack.config.js
module.exports = (env, argv) => {

// {deployEnv:"local"}로 출력
console.log(env);
///
};

 

4.2. Node 런타임에 직접 환경 변수를 주입한다.

webpack 같은 번들러에 상관없이 환경 변수를 주입하는 방법도 있다.

예컨대, 리눅스에서 node를 실행할 때는 `NODE_ENV=local node test.js`나, npm에서라면 아래처럼 package.json으로 설정이 가능하다.

이런 방식은 일시적으로 OS에 환경변수를 주입한다.

 "test": "NODE_ENV=local node test.js"

 

 

cross-env로 OS 간 명령어 차이를 통일하기

문제는 OS마다 노드 런타임 환경에 환경 변수를 주입하는 문법이 다르다는 것이다.

mac과 리눅스는 위 방법으로 가능하지만, 윈도우의 cmd나 powershell에서 주입을 하려면 다음같이 실행해야 한다.

# 일시적으로 세션에서 NODE_ENV를 local로 설정함
$env:NODE_ENV="local"; node test.js

 

참고로, package.json에 script 명령어로  ` "test": "NODE_ENV=local node test.js"` 이렇게 설정하고 실행하는 건 powershell에서도 가능하다. node 내부에는 OS간 호환성을 맞춰주는 기능이 내장되어 있기 때문이다.

 

하지만, 만일을 대비하려면 cross-env를 사용하는 걸 권장한다.

cross-env는 OS간 다른 명령어의 호환성을 맞춰주는 모듈이다.

 

사용 방법은 아래처럼 프로젝트에 설치를 한다.

> npm install cross-env

 

그리고 명령어 앞에 `cross-env`를 아래처럼 붙여주면 된다

// @package.json

  "scripts": {
    "test": "cross-env NODE_ENV=local node test.js"
  },

 

 


5. 결론 정리


  • NODE_ENV는 node 생태계 내 주요 프레임워크나 CLI 도구에서 실행 환경 분기처리에 표준처럼 사용하는 환경 변수다.
  • 프로젝트에서 실행 분기 처리에 NODE_ENV를 사용하면 프레임워크 및 CLI의 동일한 환경 변수에 의해 오버라이드가 생기거나 충돌이 발생할 수 있다.
  • 따라서, 번들러 cli에서 제공하는 환경변수 주입 명령어를 사용하거나 NODE 환경에 직접 환경 변수를 임시로 주입해서 분기처리를 하고, NODE_ENV 대신, 다른 플래그 변수를 사용한다.