ice rabbit programming

[JS][WebPack] WebPack에서 환경변수 사용하기 본문

Development/JavaScript

[JS][WebPack] WebPack에서 환경변수 사용하기

판교토끼 2020. 10. 24. 00:56

최근 Vue.js를 사용하며 WebPack을 사용했는데, local에서 proxy table의 사용을 환경 변수에 따라 다르게 설정하고 싶었다. (webpack이 아닌 vue-cli를 활용한다면 이 글을 참고)

dotenv 패키지 적용

그러던 중에 dotenv 패키지를 찾아서 적용하였다.

npm install dotenv

 

dotenv 패키지는 여러 프레임워크에 존재하는데, .env 파일을 통해 환경 변수를 설정해주는 패키지이다.

const dotenv = require('dotenv');

dotenv.config();

이렇게 간단하게 사용할 수가 있는데, dotenv.config 내에 아무 것도 명시해주지 않으면 루트에 있는 .env 파일을 찾아 적용하게 된다. 경로를 지정해주고 싶으면 아래와 같이 적으면 된다.

dotenv.config({
  path: './env/local.env'
});

이러면 process.env에 .env 파일에 있는 환경 변수가 등록된다(ex. process.env.API_URL). 단, webpack 설정 단계에서이며, client 내에서 사용하려면 후술할 플러그인을 적용해야 한다.

본인은 local, dev, prod 세 가지를 넣고 싶어서, 루트 디렉토리에 env 폴더를 생성한 후에 로컬, 개발 서버, 운영 서버에 해당하는 local.env, dev.env, prod.env 세 파일을 만들었다.

// ./env/local.env
API_URL="http://localhost:5000"

npm 실행 scripts를 통해 전달

사실 webpack 버전 4로 하는 설명이 많은데, 필자는 webpack 버전 3을 사용하고 있어서 좀 헤맸었다. 최근에 시작한 프로젝트인데 웹 개발자가 아니다보니 잘 몰라 버전을 최신으로 맞추지 못한 문제였다. 어쨌거나 아래에서는 버전4와 버전3에 대해서 둘 다 다루겠다.

webpack 버전 4

버전 4에서는 실행 시에 --env 옵션 뿐 아니라 custom 옵션도 줄 수 있다.

npm run dev --api local

 

위와 같이 주면, option에 api라는 속성이 담긴다. 이런 점을 이용해서, package.json에 있는 scripts를 수정한다. scripts에는 dev, start, test, lint 등 이미 여러 가지가 정의되어 있을텐데, 자유롭게 수정/추가/삭제가 가능하다.

...
"scripts": {
  ...
  "dev-local": "webpack-dev-server --mode development --api local",
  "dev-dev": "webpack-dev-server --mode development --api dev",
  "dev-prod": "webpack-dev-server --mode development --api prod",
  ...
},
...

webpack 버전 3에서는 --mode를 줄 수 없지만(NODE_ENV가 자동으로 development) webpack 4에서는 --mode를 줄 수 있다. 여기서는 환경 자체를 바꿀 것은 아니라 모두 동일하에 development를 주었고, 뒤에 넘겨주는 것만 다르게 구성했다.

const webpack = require('webpack');
const HTMLWeebPackPlugin = require("html-webpack-plugin");
const dotenv = require('dotenv');

module.exports = (env, options) => {
  dotenv.config({
    path: `./env/${options.api || 'local'}.env`
  });

  return {
    plugins: [
      new HTMLWeebPackPlugin({
        template: "./src/index.html",
        filename: "./index.html"
      }),
      // 아래 두 플러그인을 추가하면, client 내부의 process.env에도 추가된다.
      new webpack.DefinePlugin({
        'process.env.API_URL': JSON.stringify(process.env.API_URL)
      }),
      new webpack.EnvironmentPlugin(['API_URL'])
    ]
  };
};

5번째 줄의 env는 --env로 넘겨지는 것을 받으며, options는 그 외에 사용자가 custom으로 넘겨준 것을 받는다. 여기서는 options.api를 받을 수 있다.

webpack 버전 3

webpack 버전 3에서는 --mode도, custom도 줄 수 없어 조금 헤맸지만, --env는 동일하게 적용이 가능하였다. 버전 4에서와 거의 동일하였지만 넘겨주고 받는 방식만 다르게 했다.

...
"scripts": {
  ...
  "dev-local": "webpack-dev-server --mode development --env.api local",
  "dev-dev": "webpack-dev-server --mode development --env.api dev",
  "dev-prod": "webpack-dev-server --mode development --env.api prod",
  ...
},
...

 

const webpack = require('webpack');
const HTMLWeebPackPlugin = require("html-webpack-plugin");
const dotenv = require('dotenv');

module.exports = (env) => {
  dotenv.config({
    path: `./env/${env.api || 'local'}.env`
  });

  return {
    plugins: [
      new HTMLWeebPackPlugin({
        template: "./src/index.html",
        filename: "./index.html"
      }),
      // 아래 두 플러그인을 추가하면, client 내부의 process.env에도 추가된다.
      new webpack.DefinePlugin({
        'process.env.API_URL': JSON.stringify(process.env.API_URL)
      }),
      new webpack.EnvironmentPlugin(['API_URL'])
    ]
  };
};

만일 webpack.dev.config.js의 proxy table을 이것을 이용해서 바꾸고 싶다면 아래와 같이 사용하면 된다. 다만 webpack 설정은 버전이나 사용자에 따라 상이할 수 있으니 보고 적절하게 변환하여 적절한 곳에 넣어주는 것이 좋다.

devConfig.devServer.proxy["/api"].target = process.env.API_URL