Logo

웹팩(Webpack) DefinePlugin, EnvironmentPlugin 사용법

웹팩은 유연하게 웹팩의 기능을 확장할 수 있도록 플러그인(Plugin) 시스템을 제공하고 있습니다. 일반 개발자도 플러그인을 통해서 웹펙에 추가하고 싶은 기능을 구현할 수 있으면 npm 저장소에 올려서 커뮤니티에 공개할 수 있습니다. 보통 여러 종류의 플러그인을 조합함으로써 웹펙의 번들링 과정동안 다양한 부가 작업을 처리합니다.

이번 포스팅에서는 웹팩에서 자주 사용되는 플러그인인 DefinePlugin과 EnvironmentPlugin에 대해서 알아보도록 하겠습니다.

실습 프로젝트 셋업

먼저 실습 프로젝트를 만들겠습니다. 새로운 디렉터리에 NPN 프로젝트를 만든 후, 웹팩과 웹팩 CLI 패키지를 설치합니다.

$ mkdir webpack-plugins
$ cd webpack-plugins
$ npm init -y
$ npm i -D webpack webpack-cli

그 다음, package.json 파일에 웹팩 빌드 스크립트를 추가합니다.

  • package.json
  "scripts": {
    "build": "webpack"
  },

그 다음, 기본적인 웹팩 설정을 위해서 webpack.config.js 파일을 생성합니다.

  • webpack.config.js
module.exports = {};

그 다음, src/index.js 파일에 다음과 같은 자바스크립트 소스 코드를 작성합니다.

  • src/index.js
const message = "The app is running.";
const textNode = document.createTextNode(message);
document.body.appendChild(textNode);

이제, 터미널에서 npm run build 커맨드를 실행시키면 위에서 작성한 자바스크립트 코드가 빌드되어 dist/main.js 파일이 생성됩니다.

$ npm run build

> webpack-plugins@1.0.0 build /temp/webpack-plugins
> webpack

Hash: 59cbce35117625b54844
Version: webpack 4.41.0
Time: 63ms
Built at: 09/25/2019 9:48:53 PM
  Asset     Size  Chunks             Chunk Names
main.js  3.9 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 127 bytes {main} [built]

마지막으로, 웹팩으로 빌드한 자바스크립트 코드를 로딩하는 index.html 파일을 작성합니다.

  • index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Plugins</title>
  </head>
  <body>
    <script src="./dist/main.js"></script>
  </body>
</html>

이제, 브라우저에서 index.html 파일을 열어보면 화면에 The app is running.이라고 표시가 될 것입니다.

참고로 실습 프로젝트가 제대로 만들어졌다면 다음과 같은 디렉터리 구조를 가지게 될 것입니다.

.
├── dist
│   └── main.js
├── index.html
├── node_modules
├── package-lock.json
├── package.json
├── src
│   └── index.js
└── webpack.config.js

DefinePlugin

웹팩에서 제공하는 DefinePlugin은 모든 자바스크립트 코드에서 접근이 가능한 전역 변수를 선언하기 위해서 사용되는 플러그인입니다.

이렇게 접근이 용이한 전역 변수를 지나치게 사용하면 글로벌 네임스페이스가 너무 많은 변수들로 오염되어 유지보수성 저해하게 되므로 전역 변수를 반드시 필요한 상황에서만 사용하시기 바랍니다.

DefinePlugin을 사용하는 방법은 webpack.DefinePlugin 생성자에 선언하고 싶은 전역 변수를 객체 형태로 넘긴 다음, 웹팩 설정에서 plugins 옵션으로 추가해주면 됩니다. 예를 들어, 다음과 같이 웹팩 설정하면 APP_NAME이라는 전역 변수에 My app이라는 값을 할당하고, VERSION이라는 전역 변수에 v0.1이라는 값이 할당이 됩니다.

  • webpack.config.js
const webpack = require("webpack");

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      APP_NAME: JSON.stringify("My app"),
      VERSION: JSON.stringify("v0.1"),
    }),
  ],
};

여기서 전역 변수의 값을 JSON.stringify() 함수로 문자열 값을 감싸줘야 한다는 것에 주의바랍니다.

그 다음, 이렇게 선언한 전역 변수를 사용하도록 자바스크립트 소스 코드를 다음과 같이 수정한 후에 다시 웹팩 빌드를 돌립니다.

  • src/index.js
const message = `${APP_NAME} is running. (version: ${VERSION})`;
const textNode = document.createTextNode(message);
document.body.appendChild(textNode);

자 이제, 브라우저에서 index.html 파일을 열어보면 화면에 My app is running. (version: v0.1)이라고 표시가 될 것입니다.

많이 하는 실수

DefinePlugin을 사용하시면서 많이 하는 실수가 브라우저의 콘솔에 선언한 전역 변수를 console.log(APP_NAME)와 같이 출력하시려다가 다음과 같은 오류를 만나시는 겁니다.

Uncaught ReferenceError: APP_NAME is not defined
    at <anonymous>:1:13

DefinePlugin으로 선언한 전역 변수는 어디까지나 웹팩이 소스 코드를 빌드하는 동안에만 사용되기 때문에 이런 식으로 브라우저 런타임에는 접근이 불가능합니다. 실제로 dist/main.js 파일을 열어 웹팩이 빌드한 자바스크립트 코드를 보면, 이미 전역 변수들이 할당한 값으로 대체되었음을 알 수 있습니다.

const message = `${\"My app\"} is running. (version: ${\"v0.1\"})`;

따라서 브라우저로 이미 빌드된 파일을 사용하는 index.html을 열고, 아무리 콘솔에 전역 변수를 출력해보려고 해도 되지 않는 것입니다.

EnvironmentPlugin

웹팩에서 제공하는 EnvironmentPlugin은 노드 런타임(Node runtime)에서 process.env에 저장되는 환경 변수를 전역 변수로 등록하기 위한 플러그인입니다. 환경 변수는 일반적으로 애플리케이션의 배포 환경에 따라의 설정값을 다르게 설정하기 위해서 사용합니다. 대표적인 예로, 개발 환경에서 상용 환경보다 더 많은 로그를 남기고 싶은 경우를 들 수 있습니다.

EnvironmentPlugin은 사용하는 방법은 webpack.EnvironmentPlugin 생성자에 필요한 환경 변수를 배열 형태로 넘긴 다음, 웹팩 설정의 plugins 옵션으로 추가해주면 됩니다. 예를 들어, 다음과 같이 웹팩 설정을 하면 DEBUG라는 환경 변수의 값이 process.env.DEBUG라는 전역 변수에 할당이 됩니다.

  • webpack.config.js
const webpack = require("webpack");

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      APP_NAME: JSON.stringify("My app"),
      VERSION: JSON.stringify("v0.1"),
    }),
    new webpack.EnvironmentPlugin(["DEBUG"]),
  ],
};

그 다음, 이렇게 등록된 DEBUG 환경 변수의 값이 on 경우에만 콘솔에 로그를 찍도록 자바스크립트 소스 코드를 다음과 같이 수정합니다.

  • src/index.js
if (process.env.DEBUG === "on") {
  console.log(`APP_NAME:`, APP_NAME);
  console.log(`VERSION:`, VERSION);
}
const message = `The app is running.`;
const textNode = document.createTextNode(message);
document.body.appendChild(textNode);

자, 이제 빌드를 할 때 DEBUG 환경 변수의 값을 뭐로 주느냐에 따라 로그가 찍힐 수도 있고 안 찍힐 수도 있습니다.

$ DEBUG=on npm run build

위와 같이 빌드 커맨드 앞에 DEBUG=on를 붙여서 실행을 하면, 브라우저 콘솔에 다음과 같이 위에서 DefinePlugin으로 선언했던 전역 변수들이 출력될 것입니다.

APP_NAME: My app
index.js:3 VERSION: v0.1

반대로 아래와 같이 빌드 커맨드 앞에 DEBUG=off를 붙이거나 아무 것도 안 붙이고 실행을 하면, 브라우저 콘솔에는 아무것도 출력되지 않을 것입니다.

$ DEBUG=off npm run build
$ npm run build

기본값을 설정하고 싶다면?

만약에 디폴트로 로그가 출력되고, 명시적으로 DEBUG 환경 변수를 off로 설정했을 때만 로그가 출력되지 않게 하고 싶을 때는 어떻게 해야할까요? 그럴 때는, webpack.EnvironmentPlugin 생성자의 인자로 배열이 아닌 객체의 형태로 기본값을 설정해주면 됩니다.

  • webpack.config.js
const webpack = require("webpack");

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      APP_NAME: JSON.stringify("My app"),
      VERSION: JSON.stringify("v0.1"),
    }),
    new webpack.EnvironmentPlugin({ DEBUG: "on" }),
  ],
};

이렇게 웹팩 설정을 해주면, 환경 변수 없이 그냥 npm run build 커맨드를 실행했을 때, process.env.DEBUG 전역 변수의 값이 on이 되기 때문에 로그가 찍히게 됩니다. 로그를 찍기 싶지 않은 경우에만 명시적으로 환경 변수를 앞에 붙여서 DEBUG=off npm run build 커맨드를 실행하면 됩니다.

마치면서

DefinePlugin과 EnvironmentPlugin이 햇갈리시는 분들은 EnvironmentPlugin을 환경 변수 전용 DefinePlugin이라고 생각하시면 이해가 쉬우실 것 같습니다. 따라서 DefinePlugin를 이용해서 EnvironmentPlugin로 할 수 있는 모든 설정을 할 수가 있으며, 단지 EnvironmentPlugin를 사용하는 이유는 설정을 좀 더 간편하게 하기 위함입니다.

예를 들어, 위 실습 예제에서 EnvironmentPlugin로 작성한 아래 설정은

new webpack.EnvironmentPlugin(["DEBUG"]);
new webpack.EnvironmentPlugin({ DEBUG: "on" });

DefinePlugin를 이용해서 다음과 같이 각각 대체할 수 있습니다.

new webpack.DefinePlugin({
  "process.env.DEBUG": JSON.stringify(process.env.DEBUG),
});
new webpack.DefinePlugin({
  "process.env.DEBUG": JSON.stringify(process.env.DEBUG) || "on",
});

본 포스팅에서 다룬 2개의 플러그인에 더 세부적인 사항은 아래 공식 웹팩 레퍼런스를 참고 바라겠습니다.

Webpack 관련 포스팅은 Webpack 태그를 통해서 쉽게 만나보세요!