우리는 Webpack이 왜 필요할까?
본 글은 2020년에 작성된 글입니다. 프론트엔드 개발 중이라면 Webpack이라는 기술에 대해 필수적으로 마주치게 된다. 이번 포스팅은 Webpack이 무엇인지, 왜 필요한지에 대해 찬찬히 알아보려한다. W
seogeurim.tistory.com
지난 포스팅에서 Webpack이 무엇이며 왜 쓰는지에 대해 알아보았다. 다시 한 번 그 내용을 정리하자면 다음과 같다.
- Webpack은 모듈 번들러이다.
- 프로젝트 규모가 커지고 JavaScript가 발전(모듈 시스템)하면서 요청하는 파일들이 많아졌다.
- 그 많은 파일들을 모듈 번들러가 합쳐서 요청하는 파일의 수를 줄일 수 있다.
- 번들(합쳐진 파일)이 너무 커진다면 초기 로딩 속도가 느려지는 문제가 발생할 수 있고, 청크, 캐시, 코드 스플릿 등을 도입해 해결할 수 있다.
이번 포스팅에서는 이러한 Webpack을 적용해 간단한 환경을 설정하는 법에 대해 알아보려 한다.
Webpack 환경 구성
우선 사용할 Webpack의 버전은 다음과 같다. (Webpack v5)
"webpack": "^5.44.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
Webpack은 버전별로 설정하는 방법이 조금씩 다를 수 있으니 버전에 따른 문서를 확인하는 것이 중요하다.
우선 devDependency로 webpack
, webpack-cli
, webpack-dev-server
를 추가해준다.
yarn add webpack webpack-cli webpack-dev-server -D
// or
npm install webpack webpack-cli webpack-dev-server --save-dev
webpack.config.js
webpack.config.js
파일은 webpack 옵션들을 설정할 수 있는 파일이다. webpack
명령어가 실행되면 해당 파일을 읽어 그 내용으로 빌드를 진행한다. Webpack v4부터는 config 파일을 설정하지 않는다면 디폴트 설정값으로 빌드한다고 한다.
// webpack.config.js
const path = require('path');
module.exports = {
entry: {
app: './src/index.js',
},
output: {
path: path.resolve(__dirname, './dist'),
filename: 'bundle.js',
},
};
- entry : webpack이 번들링할 때는 특정 지점에서부터 파일 간의 의존성을 찾아가며 번들링한다. entry는 그 '특정 지점', 즉 번들링의 시작점을 말한다.
- output : 번들링한 결과물을 어디로 내보낼지 지정한다. 위와 같이 설정할 경우 메인 결과물인
bundle.js
는'./dist/bundle.js'
에, 그 외 파일은./dist
폴더에 보내진다.
가장 기본적인 entry와 output 옵션을 시작으로 다양한 옵션들에 대해 알아보자.
mode
production, development 등 환경에 따라 다른 webpack 설정을 적용하고 싶다면 다음과 같은 방법이 있다.
webpack --config webpack.config.[envname].js
: 특정 이름의 config 파일을 가지고 번들링한다.webpack --mode=production
: webpack 명령어 실행 시 mode 플래그를 준다.- config 파일에 mode를 명시한다.
module.exports = { mode: 'development', //...
production(default), development, none 의 세 가지 mode 옵션이 존재한다.
loader
loader를 설정해주지 않으면 webpack은 JavaScript와 JSON 파일만 번들링한다. 다른 형식의 파일들을 번들링하기 위해서 loader를 사용한다.
module: {
rules: [
{
test: /* 설정한 파일 형식에 대한 정규식 */,
use: {
loader: '로더의 이름',
options: {
/* 로더 옵션 설정 */
},
},
exclude: /* 컴파일에서 제외할 내용 */,
},
],
},
위 형식으로 loader를 설정해주면 된다. webpack은 entry부터 번들해 나가면서 test에 작성한 정규식에 해당하는 파일을 찾으면 loader에 적용하게 된다.
plugins
plugins를 통해 Webpack 설정과 관련된 플러그인을 설치하고 도입할 수 있다.
html-webpack-plugin
플러그인을 활용하면 모든 번들을 포함하는 HTML 문서를 자동으로 생성할 수 있다.
//...
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
//...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
//...
};
위와 같이 작성한 후 빌드해보면 bundle.js
를 스크립트 파일로 포함하는 index.html
파일이 output path에 생성된다.
sourceMap
빌드 후 개발자 도구를 열어 확인해보면 디버깅 시 bundle.js
코드를 확인해야 하는 것을 알 수 있다. 즉 디버깅이 불가능하다.
sourceMap이란 빌드한 파일과 원본 파일을 서로 연결시켜주는 기능이다. sourceMap 설정을 통해 bundle.js
코드의 특정 부분이 원본 코드의 어떤 부분인지 확인할 수 있고, 그를 통해 디버깅을 수행할 수 있다.
devtool: 'eval-cheap-source-map'
위와 같이 설정할 수 있고 소스 맵 설정 옵션 비교표를 통해 팀에 알맞은 설정을 적용하면 된다.
devServer
Webpack을 사용해 [빌드 후 실행, 코드 수정 후 빌드 후 실행, ...] 과정을 반복하면 개발 시 매우 불편할 것이다. webpack-dev-server
를 사용하면 이 문제를 해결할 수 있다. devServer를 통해 로컬 서버를 열어 코드를 수정했을 때 다시 빌드하고, 핫리로드를 적용해 바로바로 빌드 결과를 확인할 수 있다.
devServer: {
contentBase: path.resolve(__dirname, './dist'),
compress: true,
hot: true,
port: 9000,
},
위와 같이 devServer에 여러 설정들을 추가할 수 있다. 추가 설정을 살펴보고 팀에 알맞은 설정을 적용하면 된다.
devServer는 webpack serve
명령어를 통해 실행할 수 있고, "dev": "webpack serve --mode development --open"
와 같이 package.json에 script를 작성해두는 것이 좋다.
환경 설정 중 이런 오류가 난다면?
Webpack을 처음 다뤄볼 때, 다음의 오류에 고민을 했던 경험이 있어서 남겨본다.
1. output.path에 상대 경로를 썼을 때
에러 내용 : configuration.output.path: The provided value '../dist' is not an absolute path!
path에는 절대 경로를 써야 하고, 그를 위해 path.join()
또는 path.resolve()
메서드를 사용하면 된다.
두 메서드의 차이점은/
에 대한 처리 방식에 있다. join 메서드는/
를 만나도 계속 연결하여 경로를 만들고, resolve 메서드는/
를 만나면 절대경로로 인식하여 이전 경로를 모두 무시한다.
path.join('/a', '/b') // Outputs '/a/b' path.resolve('/a', '/b') // Outputs '/b'
2. loader 작성 중 module.rules.use.loader에 ['babel-loader']로 작성했을 때
에러 내용 : configuration.module.rules[0].use.loader should be a non-empty string.
loader는 배열이 아니라 string으로 작성하여야 한다.
3. webpack-dev-server로 실행했을 때 프로젝트가 수정되면 자동 빌드되어 보여져야 하는데, 그렇지 않았다.
처음에index.html
을 public 디렉토리에 두고 그 파일 내에<script>
로 번들된 파일의 경로를 명시했었다. 이 경우 build했을 때는 문제가 되지 않았지만 devServer로 실행 시에는 수정 내역이 리로드되지 않는 문제가 발생하였다.
devServer의 번들된 결과물은 따로 저장되지 않고 메모리에 저장된다. 따라서 그 경로에 차이가 있지 않을까라는 추측을 하게 되었고, html-webpack-plugin
플러그인을 활용해 번들된 파일이 index.html
에 자동으로 연결되도록 하여 해결할 수 있었다.
나만의 boilerplate를 만들어보자!
Webpack에 대해 어느 정도 이해했다면 프로젝트 기술에 알맞게 나만의 boilerplate를 만들어보는 것을 추천한다. 아래는 내가 생성한 boilerplate들이다. 이 포스팅을 읽었다면 한 번씩 구경오시길!!
GitHub - Seogeurim/webpack-es6-boilerplate: A minimal webpack 5 boilerplate 🌐
A minimal webpack 5 boilerplate 🌐. Contribute to Seogeurim/webpack-es6-boilerplate development by creating an account on GitHub.
github.com
GitHub - Seogeurim/react-typescript-boilerplate: React X TypeScript boilerplate 🌐
React X TypeScript boilerplate 🌐. Contribute to Seogeurim/react-typescript-boilerplate development by creating an account on GitHub.
github.com
GIVEME-STAR
🌟
참고 자료
웹팩-Webpack-의-개념과-vanilla-js-boilerplate
Node path.join() vs path.resolve()
'Web' 카테고리의 다른 글
내 프로젝트에 ESLint & Prettier 도입하기 (VSCode) (0) | 2021.12.06 |
---|---|
우리는 Webpack이 왜 필요할까? (0) | 2021.10.31 |
npm? yarn? 그 차이가 뭐길래... (0) | 2021.10.31 |