티스토리 뷰
Vue.JS와 Electron.JS, React.JS 등.. 자바스크립트 프론트엔드 어플리케이션을 CLI를 사용하여 프로젝트를 생성하면 자연스럽게 따라 설치되는 모듈 번들러(module bundler)였습니다. (모듈 번들러를 선택 할 수 있다면 webpack를 선택해서 사용했습니다.) 이번 포스트에서는 자연스럽게 사용했던 webpack이라는 모듈 번들러에 대해 이야기하려고 합니다.
1. 모듈 번들러가 무엇인가요?
모듈 번들러를 간단히 이야기 하면, 여러개의 파일을 하나의 파일로 묶어주는 라이브러리를 이야기 합니다.
위의 그림은 webpack의 공식문서의 첫 페이지에 등장하는 그림입니다. 위의 그림을 보면 모듈 번들러가 무엇인지가 대략 파악이 가능합니다. 모듈 번들러는 파일의 종속성을 스스로 파악하여, 종속성이 있어 서로 엮여 있는 파일을 하나의 파일로 묶어주는 역할을 합니다.
2. webpack을 왜 사용하나요?
webpack에 개념을 이야기하기 앞서 왜 webpack을 사용해야 하는지, webpack과 같은 모듈 번들러를 사용하는 이유와 장점에 대해 이야기 해 보도록 하겠습니다.
1) 네트워크 병목현상을 해결 할 수 있습니다.
HTML에서 <script />
로 자바스크립트 파일을 실행 할 수 있습니다. 너무 많은 자바스크립트 파일을 로드할 경우, 네트워크의 병목현상이 발생하게 됩니다. 이러한 문제를 하결하기 위해 하나의 큰 자바스크립트 파일을 로드하면 되지만, 하나의 자바스크립트 파일로 개발할 경우, 가독성과 유지보수 효율이 떨어지게 됩니다. webpack과 같은 모듈 번들러는 여러 파일을 하나의 파일로 묶어주기 때문에, 네트워크 병목현상을 최소화 할 수 있습니다.
2) 모듈 단위로 개발이 가능합니다.
앞에서 이야기 한 것 같이 모듈 번들러를 사용하면 모듈 단위의 코딩이 가능합니다. 모듈 단위 코딩은
- 가독성과 유지보수 효율을 높입니다.
모듈 단위로 기능을 구분하여 코딩이 가능하기 때문에 코드의 가독성이나, 유지보수 하는데 효율이 증가하게 됩니다.
- 스코프에 신경 쓰지 않고 개발이 가능하게 합니다.
// code_1.js
var number = 1;
console.log(number + 1);
// code_2.js
var number = 1;
console.log(number * number);
code_1.js
와 code_2.js
두 자바스크립트 파일을 HTML에 <script />
로 로드를 한다면 number
변수가 동일한 스코프에 선언되어 충돌이 발생하게 됩니다. 복잡한 프로젝트일 경우에는 예상하지 못한 동작을 하게 될 수 있습니다. (스코프-Scope에 관련된 내용은 이곳을 참고해 주세요.) 모듈 번들러를 사용하게 되면 모듈 번들러는 IIFE(즉시실행함수)로 모듈을 변경해 주기 때문에, 스코프에 신경 쓰지 않고 개발을 할 수 있게 됩니다. (즉시실행함수-IIFE에 관련된 내용은 이곳을 참고해 주세요.)
- 라이브러리 종속 순서를 신경 쓰지 않아도 됩니다.
<!-- index.html -->
<html>
<head>
<script src="need-jqeury.js" />
<script src="jquery.js" />
</head>
<body>
<div id="test" />
</body>
</html>
// need-jqeury.js
$('#test').css('display', 'none');
index.html
에 <script />
로 neee-jquery.js
와 jquery.js
순서로 로드 할 때, jquery.js
가 로드 되기 전에 need-jquery.js
가 로드 되어 jquery를 사용하기 때문에 위 코드는 에러가 발생됩니다. 모듈 벌들러를 사용한다면 위와 같은 로드 순서를 신경쓰지 않아도 됩니다.
3) 코드를 압축/최적화 할 수 있습니다.
모듈 번들러를 사용하면, 여러개의 파일을 하나로 파일로 묶어 주며, 파일의 크기를 줄여 페이지 로딩을 빠르게 합니다. 모듈 번들러는 여러개의 파일들을 묶어 하나의 파일로 만들어 줄 때, 종속성을 알아서 확인하여 사용하지 않은 파일은 포함하지 않고 하나의 파일로 만들어 줍니다. webpack의 mode config에 따라 혹은 설정한 플러그인에 따라 코드에 따라 압축/최적화를 선택 할 수 있습니다.
4) ES6 버전 이상의 스크립트를 사용할 수 있습니다.
Babel은 ES6 이상의 자바스크립트 문법을 ES5 버전의 자바스크립트 문법으로 변환시켜주는 트랜스 파일러 입니다. webpack은 로더(babel-loader)를 통해, Babel이라는 트랜스파일러를 이용하여 ES6 이상의 자바스크립트를 ES5로 만들 수 있습니다. webpack과 babel을 사용하여, 오래된 버전의 브라우저에서도 ES6 버전 이상의 자바스크립트 문법 사용이 가능해집니다.
5) LESS, SCSS를 사용할 수 있습니다.
babel-loader와 동일하게 webpack은 style-loader와 css-loader라는 로더를 사용하여 LESS, SCSS를 사용할 수 있게 합니다.
3. webpack 컨샙
webpack의 핵심 개념을 이해하기 위해서는 Entry, Output, Loader, Plugins, mode를 이해하면 됩니다.
1) Entry
위의 그림의 그래프를 종속성 그래프라고 합니다. 종속성 그래프의 시작점을 Entry라고 합니다. 위의 그림을 예로 들면, 노란색 박스의 자바스크립트 파일을 Entry라고 합니다.
webpack은 config 파일을 통해 여러 설정을 할 수 있습니다. entry 역시 config 파일에 파일 위치를 설정할 수 있으며, 여러개의 entry를 지정하는 것도 가능합니다. config 파일에 entry가 설정 되어 있지 않다면 기본값은 ./src/index.js
입니다.
// webpack.config.js
module.export = {
entry: './path/to/my/entry/file.js'
/* 여러개의 entry 선언이 가능합니다.
entry: {
index: './path/to/my/entry/index.js',
file: './path/to/my/entry/file.js'
} */
}
webpack.config.js
는 entry
를 ./path/to/my/entry/file.js
로 설정한 코드입니다.
2) Output
output 설정으로 생성한 번들을 저장할 위치를 지정할 수 있습니다. config 파일에 output이 설정되어 있지 않다면 기본 값은 ./dist/main.js
입니다. 생성된 번들 파일들이 ./dist
디렉토리 밑으로 들어가게 됩니다.
// webpack.config.js
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
/* 여러개의 entry가 정의 되었을 때, 아래와 같이 설정이 필요합니다.
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
} */
};
output.path
: 번들된 파일을 내보낼 디렉토리 위치를 지정해 줍니다.output.filename
: 번들된 파일 이름을 지정해 줍니다.
3) Loader
webpack은 모든 파일을 모듈로 관리합니다. 하지만 webpack은 자바스크립트 파일만 읽어 올 수 있기 때문에, 스타일시트나 이미지등을 webpack이 읽을 수 있는 자바스크립트로 변경되어야 합니다. webpack이 이해 할 수 있는 모듈로 변경해 주는 역할을 Loader가 하게 됩니다.
// webpack.config.js
const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
}
};
test
: 변환 할 파일을 지정합니다.use
: 변환 할 파일에 지정할 로더를 설정합니다.
4) Plugins
Loader은 모듈을 처리하지만, Plugin은 번들된 파일을 처리합니다. Plugin은 번들된 파일을 난독화 하거나, 압축하는데 사용됩니다.
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
module.exports = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
plugin을 사용하기 위해서는 require
을 사용하여 plugins
에 추가 할 plugin을 가져와야 합니다. 또한 new
로 사용할 plugin의 인스턴스를 생성하여 plugins
에 추가해 줍니다. 위의 예제 코드에서 사용한 HtmlWebpackPlugin
plugin은 생성된 번들 파일을 자동으로 로드(<script />
로)한 HTML 파일을 생성해 주는 plugin입니다.
webpack이 제공하는 다양한 plugin은 이곳에서 확인 할 수 있습니다.
5) Mode
mode는 production, development, none 3가지 옵션이 존재합니다.
module.exports = {
mode: 'production'
};
mode의 기본값은 production입니다. 각 설정마다 내장된 최적화 옵션을 자동으로 설정하여 줍니다.
- development
// webpack.development.config.js
module.exports = {
devtool: 'eval',
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.NamedChunksPlugin(),
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
]
}
mode
를 development
로 설정했을 때, 설정되는 옵션은 위의 코드와 같습니다.
- production
// webpack.production.config.js
module.exports = {
plugins: [
new UglifyJsPlugin(/* ... */),
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
}
mode
를 production
로 설정했을 때, 설정되는 옵션은 위의 코드와 같습니다.
- none
// webpack.custom.config.js
module.exports = {
plugins: [
]
}
mode
를 none
로 설정했을 때는 어떠한 옵션도 설정되지 않습니다.
참고
'ETC...' 카테고리의 다른 글
[Svelte] 스벨트 입문 A부터 Z까지 (1) | 2020.08.07 |
---|---|
[Browser] 렌더링 최적화 (0) | 2019.12.09 |
[디자인패턴] Flux, MVC 비교 (11) | 2018.09.22 |
[디자인패턴] MVC, MVP, MVVM 비교 (57) | 2018.09.15 |
[webpack] webpack 4 사용하기 (1) | 2018.09.06 |