Logo

웹팩(Webpack) 기본 설정법 (Entry/Output/Loader/Plugins)

React나 Vue, Angular와 같은 자바스크립트 프레임워크를 기반으로 프로젝트를 하다보면 webpack.config.js라는 파일과 자주 마주치게 됩니다. 바로 웹팩 설정 파일인데요. 이번 포스팅에서는 이 설정 파일을 기본으로 한 웹팩 기본 설정법에 대해서 알아보도록 하겠습니다.

웹팩에 대한 기본 개념이나 사용법을 모르시는 분은 지난 포스팅를 먼저 읽어보시면 더 따라가기 쉬우실 겁니다.

설정 파일

웹팩을 사용할 때 반드시 설정 파일이 필요하지는 않지만, 대부분의 경우에는 설정 파일을 사용합니다. 왜냐하면 터미널에서 웹팩 커맨드를 실행할 때 마다 모든 옵션들을 붙여주는게 번거롭고, 설정 파일을 소스 저장소에 올려두면 다른 개발자들은 크게 설정이 신경쓰지 않고 협업을 할 수 있기 때문입니다.

먼저 디렉터리를 만들고 NPN 프로젝트를 초기화 후, 웹팩과 웹팩 CLI 패키지를 설치합니다. 그런 다음, 웹팩에서 디폴트로 인지하는 설정 파일 이름인 webpack.config.js로 빈 설정 파일을 하나 만들면 초기 세팅 완료입니다.

$ mkdir webpack-config
$ cd webpack-config
$ npm init -y
$ npm i -D webpack webpack-cli
$ touch webpack.config.js
  • webpack.config.js
module.exports = {};

참고로 설정 파일의 이름을 디폴트가 아닌 다른 이름을 사용하고 싶은 경우에는 웹팩 커맨드 실행 시 다음과 같이 --config 옵션을 주시면 됩니다.

$ npx webpack --config [설정 파일 이름]

Entry 설정

웹팩은 기본적으로 여러 개의 자바스크립트 모듈을 하나의 파일로 묶어내는 번들러입니다. 따라서 웹팩은 다른 모듈을 사용하고 있는 최상위 자바스크립트 파일이 어디에 있는지 알아야 하며, 설정 파일에서 이를 Entry 속성으로 명시합니다. 웹팩은 이 Entry 속성에 명시된 파일을 기준으로 의존성 트리를 만들어 하나의 번들 파일을 만들어 내게 됩니다. Entry 설정의 기본값은 ./src/index.js이고, 예제 프로젝트에서는 이를 간단하게 ./script.js로 변경해보도록 하겠습니다.

  • webpack.config.js
module.exports = {
  entry: "./script.js",
};

그리고 script.js 파일에 다음과 같이 브라우져 화면에 간단한 문자열을 표시하는 자바스크립트 코드를 작성합니다.

  • script.js
const message = document.createTextNode("Webpack Example");
document.body.appendChild(message);

그 다음, 터미널에서 npx webpack 커맨드를 실행하면 웹팩이 script.js 파일을 읽어들여 dist 디렉터리에 main.js 파일로 묶어냅니다.

$ npx webpack
npx: installed 1 in 3.571s
Path must be a string. Received undefined
C:\workspace\webpack-examples\webpack-config\node_modules\webpack\bin\webpack.js
Hash: 99f99481de3c30b2f031
Version: webpack 4.16.3
Time: 682ms
Built at: 2018-07-14 20:00:40
  Asset        Size  Chunks             Chunk Names
main.js  1010 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./script.js 94 bytes {0} [built]

dist/main.js 파일을 열어보면 웹팩이 Uglify/Minify통해 읽기 어려운 한 줄의 코드로 바꿔놓았음을 확인할 수 있습니다.

  • dist/main.js
!(function (e) {
  var t = {};
  function n(r) {
    if (t[r]) return t[r].exports;
    var o = (t[r] = { i: r, l: !1, exports: {} });
    return e[r].call(o.exports, o, o.exports, n), (o.l = !0), o.exports;
  }
  (n.m = e),
    (n.c = t),
    (n.d = function (e, t, r) {
      n.o(e, t) || Object.defineProperty(e, t, { enumerable: !0, get: r });
    }),
    (n.r = function (e) {
      "undefined" != typeof Symbol &&
        Symbol.toStringTag &&
        Object.defineProperty(e, Symbol.toStringTag, { value: "Module" }),
        Object.defineProperty(e, "__esModule", { value: !0 });
    }),
    (n.t = function (e, t) {
      if ((1 & t && (e = n(e)), 8 & t)) return e;
      if (4 & t && "object" == typeof e && e && e.__esModule) return e;
      var r = Object.create(null);
      if (
        (n.r(r),
        Object.defineProperty(r, "default", { enumerable: !0, value: e }),
        2 & t && "string" != typeof e)
      )
        for (var o in e)
          n.d(
            r,
            o,
            function (t) {
              return e[t];
            }.bind(null, o)
          );
      return r;
    }),
    (n.n = function (e) {
      var t =
        e && e.__esModule
          ? function () {
              return e.default;
            }
          : function () {
              return e;
            };
      return n.d(t, "a", t), t;
    }),
    (n.o = function (e, t) {
      return Object.prototype.hasOwnProperty.call(e, t);
    }),
    (n.p = ""),
    n((n.s = 0));
})([
  function (e, t) {
    const n = document.createTextNode("Webpack Example");
    document.body.appendChild(n);
  },
]);

Output 설정

위 섹션에서 웹팩이 번들링 결과를 dist/main.js 파일로 묶어내는 이유는 설정이 dist/main.js이기 때문입니다. 설정 파일의 Output 속성을 통해서 이 값을 다른 디렉터리와 파일로 변경할 수 있습니다. 예제 프로젝트에서는 dist/main.js 대신에 더 간단히 output.js 파일로 묶어내도록 Output 설정을 변경해보겠습니다. Entry 설정은 항상 프로젝트 디렉터리 내부이기 때문에 상대 경로로 하는 반면에, Output 설정은 항상 프로젝트 디렉터리 내부라는 보장이 없으므로 절대 경로로 한는 점에 주의 바랍니다.

  • webpack.config.js
module.exports = {
  entry: "./script.js",
  output: {
    path: __dirname,
    filename: "build.js",
  },
};

참고로 __dirname은 NodeJS에서 현재 프로젝트 디렉터리를 의미합니다. 이제 웹팩을 실행하면 프로젝트 최상위 디렉터리에 build.js 파일이 생성되었음을 확인할 수 있습니다.

$ npx webpack
npx: installed 1 in 4.402s
Path must be a string. Received undefined
C:\workspace\webpack-examples\webpack-config\node_modules\webpack\bin\webpack.js
Hash: 3cba8e4507f3a3e4998e
Version: webpack 4.16.3
Time: 1230ms
Built at: 2018-07-14 20:19:39
    Asset        Size  Chunks             Chunk Names
build.js  1010 bytes       0  [emitted]  main
Entrypoint main = build.js
[0] ./script.js 94 bytes {0} [built]

다음과 같이 build.js를 참조하는 index.html 파일을 작성 후 브라우져에서 열어보면 화면에 Webpack Example이 출력될 것입니다.

  • index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Example</title>
  </head>
  <body>
    <script src="./build.js"></script>
  </body>
</html>

Loader 설정

웹팩은 자바스크립트 뿐만 아니라, Loader를 이용하여 CSS나 이미지, 웹폰트, JSX, VUE 등 다양한 종류의 파일을 함께 번들링할 수 있습니다. (개인적으로 웹팩의 가장 강력한 기능이라고 생각합니다.) 본 예제에서는 가장 자주 사용되는 CSS 파일에 대해서만 설정을 해보겠습니다.

먼저, 웹팩이 CSS 파일을 처리할 수 있게 만들어주는 style-loadercss-loader 패키지를 설치합니다.

$ npm i --D style-loader css-loader

그리고 브라우져 글씨를 모두 빨간색으로 만드는 간단한 CSS 파일을 작성합니다.

  • style.css
body {
  color: red;
}

그런 다음, script.js 파일에서 마치 JS 파일을 임포트하듯이 CSS 파일을 임포트 합니다. 여기서 주의 사항은 반드시 style.css 앞에 ./를 붙여줘야 한다는 점입니다. 그렇지 않으면 프로젝트 최상위 디렉터리가 아닌 node_modules 디렉터리를 뒤지기 때문입니다.

  • script.js
import "./style.css";

const message = document.createTextNode("Webpack Example");
document.body.appendChild(message);

마지막으로 CSS 파일이 방금 설치한 두개의 모듈에 의해서 처리될 수 있도록 웹팩 설정을 해줘야 합니다. 설정 파일을 열어 module 속성을 추가하고, 그 안에 rules 속성을 통해 처리 규칙을 등록합니다. test 항목에 정의된 정규식에 매칭되는 파일은 use 항목에 등록된 로더를 통해서 처리되게 됩니다. 본 예제에서는 CSS 파일 처리를 위해서 test 항목에 정규식으로 확장자가 css인 파일만 인식하도록 설정하고, use 항목에 style-loadercss-loader를 차례로 나열하였습니다.

  • webpack.config.js
module.exports = {
  entry: "./script.js",
  output: {
    path: __dirname,
    filename: "build.js",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

마지막으로 다시 웹팩을 실행 후에 다시 index.html 파일을 브라우져에서 열어보면 Webpack Example이 붉은색 글씨로 표시될 것입니다.

$ npx webpack
npx: installed 1 in 2.834s
Path must be a string. Received undefined
C:\workspace\webpack-examples\webpack-config\node_modules\webpack\bin\webpack.js
Hash: 5ac38650d299445c85fc
Version: webpack 4.16.3
Time: 1042ms
Built at: 2018-07-14 20:58:41
   Asset      Size  Chunks             Chunk Names
build.js  6.74 KiB       0  [emitted]  main
Entrypoint main = build.js
[0] ./script.js 118 bytes {0} [built]
[1] ./style.css 1.04 KiB {0} [built]
[2] ./node_modules/css-loader!./style.css 185 bytes {0} [built]
    + 3 hidden moduless

다른 종류의 파일들로 그에 상응하는 로더 패키지를 제공하고 있으며, 비슷한 형식으로 설정 파일에 세팅해줄 수 있습니다.

Plugin 설정

마지막으로 Plugin 설정법에 대해서 알아보겠습니다. 플러그인을 통해서 로더로 설정이 애매한 부분들을 커버할 수 있습니다. 예를 들어, 웹팩을 실행할 때 마다 기존에 있던 번들 파일을 먼저 깔끔히 지우고 싶은 경우에는 clean-webpack-plugin 플러그인을 사용할 수 있습니다.

먼저 NPM으로 clean-webpack-plugin 플러그인을 설치합니다.

$ npm i -D clean-webpack-plugin

그리고 설정 파일에 설치한 플러그인을 임포트한 후에, plugins 속성에 임포트한 프로그인을 추가합니다.

  • webpack.config.js
const CleanWebpackPlugin = require("clean-webpack-plugin");

module.exports = {
  entry: "./script.js",
  output: {
    path: __dirname,
    filename: "build.js",
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
    ],
  },
  plugins: [new CleanWebpackPlugin("build.js")],
};

그런 다음 웹팩을 실행해보면 플러그인을 통해 build.js 파일이 지워졌다가 다시 생성되는 것을 확인할 수 있습니다. (5번째 라인)

$ npx webpack
npx: installed 1 in 2.911s
Path must be a string. Received undefined
C:\workspace\webpack-examples\webpack-config\node_modules\webpack\bin\webpack.js
clean-webpack-plugin: C:\workspace\webpack-examples\webpack-config\build.js has been removed.
Hash: 5ac38650d299445c85fc
Version: webpack 4.16.3
Time: 583ms
Built at: 2018-08-14 21:01:08
   Asset      Size  Chunks             Chunk Names
build.js  6.74 KiB       0  [emitted]  main
Entrypoint main = build.js
[0] ./script.js 118 bytes {0} [built]
[1] ./style.css 1.04 KiB {0} [built]
[2] ./node_modules/css-loader!./style.css 185 bytes {0} [built]
    + 3 hidden modules

마치면서

이상으로 웹팩의 기본적인 설정 방법에 대해서 알아보았습니다. 지금까지 잘 따라오셨다면 다음과 같이 웹팩으로 빌드가 되는 심플한 구조의 프로젝트를 얻으셨을 것입니다.

webpack-config
|- build.js
|- index.html
|- script.js
|- style.css
|- webpack.config.js
|- package.json
|- /node_modules
  • package.json
{
  "name": "webpack-config",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^1.0.0",
    "style-loader": "^0.21.0",
    "webpack": "^4.16.3",
    "webpack-cli": "^3.1.0"
  }
}

설정 항목을 최종 정리해보면 다음과 같습니다.

설정 용도
entry 입력 파일 경로
output 출력 디렉터리와 파일 이름
module > rules 로더 등록
plugins 플러그인 등록

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