Logo

웹팩(Webpack) 개발 편의 기능

웹팩은 자바스크립트 개발자들이 좀 더 쾌적한 개발 경험을 할 수 있도록 여러 가지 개발 편의 기능을 제공합니다. 이번 포스팅에서는 웹팩을 사용하면서 개발 편의성을 개선시킬 수 방법에 대해서 알아보겠습니다.

실습 프로젝트

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

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

그 다음, 다음과 같이 src/index.jsdist/index.html 파일을 작성합니다.

  • src/index.js
const message = document.createTextNode("Hello, Webpack!");
document.body.appendChild(message);
  • dist/index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Development</title>
  </head>
  <body>
    <script src="./main.js"></script>
  </body>
</html>

자 이제, 터미널에서 웹팩을 커맨드를 실행시켜 번들을 합니다. 웹팩의 디폴트 설정에 따라 src/index.js를 읽어들여 dist/main.js을 만들어냅니다.

$ npx webpack
Hash: b1885542f2ac20f161f3
Version: webpack 4.16.5
Time: 80ms
Built at: 2018-07-20 12:58:38
  Asset        Size  Chunks             Chunk Names
main.js  1010 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js 93 bytes {0} [built]

그리고 나서 브라우저에서 dist/index.html 파일을 열어보면 화면에 Hello, Webpack!이라고 표시가 될 것입니다.

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

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

코드 수정의 번거로움

Hello, Webpack! 대신에 Bye, Webpack!을 화면에 출력하려고 하고 싶다고 가정해봅시다.

먼저 src/index.js 파일을 열어서 소스 코드를 수정해야겠죠.

const message = document.createTextNode("Bye, Webpack!");
document.body.appendChild(message);

여기서 다시 브라우저를 새로고침해보면 여전히 기존 메시지가 화면에 표시됨을 알 수 있습니다. 왜냐하면, dist/index.html 파일은 src/index.js(웹팩 입력)가 아닌 dist/main.js(웹팩 출력) 파일을 참조하고 있기 때문입니다. 따라서 다음과 같이 추가로 터미널에서 웹팩을 실행시켜 번들 파일인 dist/main.js까지 업데이트 해줘야 합니다.

$ npx webpack

다시 브라우저를 새로고침해보면 의도했던바와 같이 Bye, Webpack!이 화면에 표시될 것입니다. 이처럼 웹팩을 사용하지 않을 때는 그냥 코드를 변경 후 파일을 저장만 하면 되었는데, 웹팩을 사용할 때는 매번 번들 파일까지 만들어줘야 하기 때문에 개발이 상당히 번거로워집니다.

웹팩 감시 옵션

다행히도 이렇게 매번 터미널에서 npx webpack이나 npm run build(NPM 스크립트로 등록해놓은 경우) 커맨드를 실행시키지 않고도 프로젝트의 변경 내용을 감시해서 적용해주는 기능이 있습니다. 바로 웹팩 커맨드를 실행할 때 --watch 옵션을 주는 것입니다.

$ npx webpack --watch

webpack is watching the files…

Hash: b421c06707b12960c650
Version: webpack 4.16.5
Time: 63ms
Built at: 2018-07-20 13:09:37
  Asset        Size  Chunks             Chunk Names
main.js  1010 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js 96 bytes {0} [built]

웹팩을 감시 옵션을 줘서 실행시키면 한 번 번들을 하고 마는 것이 아니라 소스 파일을 감시하는 프로세스가 계속 떠있게 됩니다. 그리고 이 프로세스가 변경 사항을 캐치해서 바로 바로 반영을 해줍니다.

다음과 같이 src/index.js 파일을 수정해보면 즉시 웹팩이 다시 번들을 수행하는 것을 터미널에서 확인할 수 있습니다.

const message = document.createTextNode("Hi, Webpack!");
document.body.appendChild(message);
Hash: 0e7ac934d3aa452e4967
Version: webpack 4.16.5
Time: 173ms
Built at: 2018-07-20 13:10:49
  Asset        Size  Chunks             Chunk Names
main.js  1010 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js 90 bytes {0} [built]

마지막으로 브라우저에서 새로고침을 해보면 Hi, Webpack!이 화면에 표시될 겁니다. 개인적으로는 이 방법으로도 충분하다고 생각하지만 아직까지도 매번 브라우저에서 새로고침을 해줘야 한다는 점이 귀찮게 느껴지실 수도 있습니다.

웹팩 개발 서버

웹팩에서 제공하는 개발 서버를 사용하면 live reloading통해, 코드 변경 분이 심지어 브라우저에서 새로고침 조차 할 필요가 없이 반영할 수 있습니다.

먼저 터미널에서 webpack-dev-server NPM 패키지를 개발 의존성으로 설치 후 웹팩 개발 서버를 구동합니다. index.html 파일이 dist 디렉터리 안에 위치하기 때문에 웹팩 개발 서버 구동 시 --content-base 옵션으로 ./dist를 넘겨주어야 합니다.

$ npm i -D webpack-dev-server
$ npx webpack-dev-server --content-base ./dist
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /work/temp/webpack-devlopment/dist
ℹ 「wdm」: wait until bundle finished: /
⚠ 「wdm」: Hash: ed36e6f00d721fd46354
Version: webpack 4.16.5
Time: 409ms
Built at: 2018-07-20 14:32:49

그리고 나서 브라우저에서 dist/index.html 파일을 직접 여는 대신에 브라우저 주소창에 http://localhost:8080을 입력하면 Bye, Webpack!이 화면에 표시될 것입니다.

src/index.js 파일을 다음과 같이 다시 수정해보면 새로고침을 하지 않아도 변경 사항이 즉시 브라우저 화면에 반영되는 것을 확인할 수 있을 것입니다.

const message = document.createTextNode("Bye~ Bye, Webpack!");
document.body.appendChild(message);

주의 사항

웹팩 개발 서버는 순수 개발용으로 디자인된 서버이기 때문에 따라서 상용 환경에서는 사용을 권장하지 않습니다. 또한 웹팩 개발 서버를 구동한 상태에서 소스 파일인 src/index.js 수정 후 번들 파일인 dist/main.js을 열어보면 변경 사항이 반영되지 않았다는 것을 알 수 있습니다. 실제 최종적으로 npx webpack 커맨드를 실행시키기 전까지는 이 번들 파일은 변경되지 않습니다. 따라서 상용 환경에 배포할 때는 반드시 실제로 웹팩을 실행시켜 번들 파일을 업데이트 해줘야 합니다.

디버깅의 어려움

웹팩을 사용할 때 애로사항이 한가지 더 생깁니다. 바로 디버깅인데요.

src/index.js 파일을 열어서 의도적으로 코드에 버그를 넣어보겠습니다. 다음과 같이 appendChild()addChild()로 바꿔줍니다.

const message = document.createTextNode("Bye~ Bye, Webpack!");
document.body.addChild(message);

브라우저 화면에서는 메시지가 사라질 것이고, 다음과 같이 번들 파일인 main.js 기준으로 에러 정보를 표시합니다.

main.js:1 Uncaught TypeError: document.body.addChild is not a function

웹팩은 기본적으로 여러 자바스크립트 파일들을 하나로 묶어서 번들 파일을 만들어내고, HTML 파일은 웹팩이 만들어낸 번들 파일을 참조합니다. 따라서 브라우저에서 코드 에러가 발생하면 번들 파일 기준으로 에러 정보가 표시됩니다. 게다가 웹팩이 만들어낸 번들 파일은 기본적으로 Uglify/Minify 처리가 되어 있기 때문에 본래 소스 코드으 어느 부분에서 에러가 발생한 건지 찾아내기가 난감해집니다.

소스 맵

웹팩의 소스 맵 기능을 이용하면 위와 같은 디버깅 문제를 해결할 수 있습니다.

먼저 다음과 같이 프로젝트 최상위 디렉터리에 webpack.config.js라는 웹팩 설정 파일을 생성하고 소스 맵 설정을 추가해줍니다.

  • webpack.config.js
module.exports = {
  devtool: "inline-source-map",
};

그리고 다시 웹팩을 실행하거나 웹팩 개발 서버를 구동해보면 다음과 같이 본래 소스 파일인 index.js 기준으로 에러 정보가 표시될 것입니다.

index.js:2 Uncaught TypeError: document.body.addChild is not a function

실제로 dist/main.js 파일을 한 번 열어보면 다음과 같이 번들된 코드 아래에 소스 맵 정보가 추가되어 있는 것을 확인할 수 있습니다.

  • dist/main.js
!function(e){var t={};function n(r){if(t[r])return t[r].exports;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,(...생략...)

마치면서

지금까지 좀 더 편하게 자바스크립트 웹 개발을 할 수 있도록 도와주는 웹팩의 기능들에 대해서 살펴보았습니다.

추가 팁으로 덧붙이면, webpack.config.js에 모든 웹팩 설정을 해두고 package.json에 웹팩 커맨드를 스크립트로 등록해놓고 사용하시면 좀 더 편리합니다.

  • webpack.config.js
module.exports = {
  devtool: "inline-source-map",
  devServer: {
    contentBase: "./dist",
  },
};
  • package.json
{
  (...생략...)
  "scripts": {
    "build": "webpack",
    "watch": "webpack --watch",
    "server": "webpack-dev-server --open"
  },
  (...생략...)
}
  • 웹팩 단순 1회 실행
$ npm run build
  • 웹팩 감시 모드 실행
$ npm run watch
  • 웹팩 개발 서버 구동 (--open 옵션 덕분에 브라우저도 자동으로 실행됨)
$ npm run server

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