최근 몇 년동안 웹 개발은 매우 작은 리소스들과 약간의 자바스크립트가 포함된 웹페이지를 시작으로, 복잡한 자바스크립트와 대규모 의존성 트리를 가지고 있는 다양한 기능을 갖춘 웹 애플리케이션으로 발전했다.
이러한 복잡성에 대응하기 위해 아래와 같은 방법을 고안했다.
- 한 프로그램으로 작동하는 하나의 파일을 여러 파일로 분할하고 구성할 수 있는 자바스크립트 모듈
- 향후 자바스크립트에서 제공될 기능을 미리 이용할 수 있게 해주는 자바스크립트 전처리기(pre-processor)와 자바스크립트로 컴파일되는 언어 (ex. CoffeeScript, TypeScript)
이러한 방법은 아주 유용하지만 파일을 브라우저가 이해할 수 있도록 번들로 묶고 변환(트랜스파일 및 컴파일)하는 이전에는 없던 추가 단계를 거쳐야 이용이 가능하다.
이 때문에 웹팩과 같은 도구가 필요해졌다.
웹팩은 프로젝트의 구조를 분석하고 자바스크립트 모듈을 비롯한 관련 리소스들을 찾은 다음 이를 브라우저에서 이용할 수 있는 번들로 묶고 패킹하는 모듈 번들러(Module bundler)다.
웹팩이란 최신 프런트엔드 프레임워크에서 가장 많이 사용되는 모듈 번들러(Module Bundler)이다. 모듈 번들러란 웹 애플리케이션을 구성하는 자원(HTML, CSS, Javscript, Images 등)을 모두 각각의 모듈로 보고 이를 조합해서 병합된 하나의 결과물을 만드는 도구를 의미한다.
모듈이란 프로그래밍 관점에서 특정 기능을 갖는 작은 코드 단위를 의미
function sum(a, b) {
return a + b;
}
function substract(a, b) {
return a - b;
}
const pi = 3.14;
export { sum, substract, pi }
이 math.js 파일은 아래와 같이 3가지 기능을 갖고 있는 모듈이다.
성격이 비슷한 기능들을 하나의 의미 있는 파일로 관리하면 모듈이 된다.
웹팩은 빌드 툴이 아니므로 그런트(Grunt)나 걸프(Gulp) 등의 태스크 러너나 빌드 시스템과는 다르지만, 이러한 툴을 대체하면서 장점을 제공할 수 있다.
그런트나 걸프 같은 빌드 툴은 정의한 경로에서 구성과 일치하는 파일을 찾는다. 따라서 구성 파일에서 이러한 파일을 변환, 조합 및 축소 하는 작업이나 단계를 지정해야 한다.
이와 달리 웹팩은 프로젝트 전체를 한 단위로 분석한다. 즉, 지정한 메인 파일에서 시작해 자바스크립트의 require(webpack commonJS 모듈 지원)과 import(ES6)문을 참고해 프로젝트의 모든 의존성을 조사하고 로더를 이용해 처리한 후 번들로 묶은 자바스크립트 파일을 생성한다.
웹팩에서 지칭하는 모듈이라는 개념은 위와 같이 자바스크립트 모듈에만 국한되지 않고 웹 애플리케이션을 구성하는 모든 자원을 의미한다. 웹 애플리케이션을 제작하려면 HTML, CSS, Javascript, Images, Font 등 많은 파일들이 필요하다. 이 파일 하나하나가 모두 모듈이다.
아래 그림과 같이 웹 애플리케이션을 구성하는 몇십, 몇백개의 자원들을 하나의 파일로 병합 및 압축 해주는 동작을 모듈 번들링이라고 한다.
웹팩에서 모든 것은 모듈이다. 자바스크립트, 스타일시트, 이미지 등 모든 것을 자바스크립트 모듈로 로딩해서 사용하도록 한다.
위 그림처럼 자바스크립트가 로딩하는 모듈이 많아질수록 모듈간의 의존성은 증가한다. 의존성 그래프의 시작점을 웹팩에서는 엔트리(entry)라고 한다.
웹팩은 엔트리를 통해서 필요한 모듈을 로딩한고 하나의 파일로 묶는다.
module.exports = {
entry: {
main: "./src/main.js",
},
}
우리가 사용할 html에서 사용할 자바스크립트의 시작점은 src/main.js 코드다. entry 키에 시작점 경로를 지정했다.
엔트리에 설정한 자바스크립트 파일을 시작으로 의존되어 있는 모든 모듈을 하나로 묶을 것이다. 번들된 결과물을 처리할 위치는 output에 기록한다.
module.exports = {
output: {
filename: "bundle.js",
path: "./dist",
},
}
dist 폴더의 bundle.js 파일로 결과를 저장할 것이다.
html파일에서는 번들링된 이 파일을 로딩하게끔 한다.
<body>
<script src="./dist/bundle.js"></script>
</body>
웹팩은 터미널에서 webpack 커맨드로 빌드할 수 있다.
웹팩은 모든 파일을 모듈로 관리한다고 했다. 자바스크립트 파일 뿐만 아니라 이미지, 폰트, 스타일시트도 전부 모듈로 관리한다. 그러나 웹팩은 자바스크립트 밖에 모른다. 비 자바스크립트 파일을 웹팩이 이해하게끔 변경해야하는데 로더가 그런 역할을 한다.
로더는 test
와 use
키로 구성된 객체로 설정할 수 있다.
test
에 로딩할 파일을 지정하고use
에 적용할 로더를 설정한다가장 간간한 예가 바벨이다. ES6에서 ES5로 변환할 때 바벨을 사용할수 있는데 test에 ES6로 작성한 자바스크립트 파일을 지정하고, use에 이를 변환할 바벨 로더를 설정한다.
마침 위 코드를 ES6로 작성했으니 로더를 이용해 ES5으로 변환해 보겠다.
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: "node_modules",
use: {
loader: "babel-loader",
options: {
presets: ["env"],
},
},
},
],
},
}
test에 자바스크립트 확장자를 갖는 파일을 정규표현식으로 지정했다. node_moudles 폴더는 패키지 폴더이므로 제외하기 위해서 exclude에 설정한다. use에 로더를 설정하는데 babel-loader 를 추가했다.
로더를 사용하기 위해서는 노드 패키지로 제공하는 로더를 npm으로 추가해야한다.
npm i --save-dev babel-loader babel-core babel-preset-env
웹팩 커맨드라인으로 빌드하고 나면 bundle.js가 ES5 문법으로 변경된것을 확인할 수 있다.
웹팩에서 알아야할 마지막 개념이 플러그인이다. 로더가 파일단위로 처리하는 반면 플러그인은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화 한다거나 특정 텍스트를 추출하는 용도로 사용할 수 있다.
UglifyJsPlugin은 로더로 처리된 자바스크립트 결과물을 난독화 처리하는 플러그인이다.
플러그인을 사용할 때는 웹팩 설정 객체의 plugins 배열에 추가한다.
const webpack = require("webpack")
module.exports = {
plugins: [new webpack.optimize.UglifyJsPlugin()],
}
다음의 글을 참고하였습니다.
- https://joshua1988.github.io/webpack-guide/webpack/what-is-webpack.html
- https://jusungpark.tistory.com/52
- https://jeonghwan-kim.github.io/js/2017/05/15/webpack.html#:~:text=%EC%9D%98%EC%A1%B4%EC%84%B1%20%EA%B7%B8%EB%9E%98%ED%94%84%EC%9D%98%20%EC%8B%9C%EC%9E%91%EC%A0%90%EC%9D%84,%EC%84%A4%EC%A0%95%ED%8C%8C%EC%9D%BC%20%EB%B6%80%ED%84%B0%20%EC%8B%9C%EC%9E%91%ED%95%B4%20%EB%B3%B4%EC%9E%90.&text=%EC%9A%B0%EB%A6%AC%EA%B0%80%20%EC%82%AC%EC%9A%A9%ED%95%A0%20html%EC%97%90%EC%84%9C,%2Fmain.js%20%EC%BD%94%EB%93%9C%EB%8B%A4.