웹팩이란?
웹사이트를 만들 때는 다양한 파일들이 필요하며 파일들간의 의존성이 생길 수밖에 없다. 웹팩은 이런 각각의 파일들을 JS의 모듈(module) 개념으로 보고 여러개의 모듈을 번들링시키는 역할을 한다. 그렇다면 웹팩을 사용하면 어떤 장점이 있을까?
- HTML/CSS/JS/이미지 등의 압축과 CSS의 전처리 등을 알아서 해준다.
- Babel을 적용하여 ES6+의 문법을 사용할 수 있게 해준다.
- 번들링을 하기 때문에 SPA라면 1개의 파일, 그게 아니더라도 훨씬 파일 수를 줄여줘서 HTTP 요청이 현저히 줄어든다.
이외에도 많은 강점들이 있으며 결론적으로는 웹팩이 “전처리를 편리하게 수행해주는 모듈 번들러” 라고 할 수 있다.
웹팩의 여러가지 개념
entry
웹팩이 빌드를 할 때 진입하는 JS 파일로, SPA라면 1개이고 그게 아니라면 여러개이다.
module.exports = {
entry: './js/entry.js',
};
output
웹팩이 빌드한 파일들에 대한 옵션으로 파일의 이름과 경로를 지정한다.
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.js',
},
};
loader
웹팩을 빌드하기 전의 전처리들(압축, CSS 전처리, Babel 등)을 하기 위한 옵션이다.
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}
]
}
}
test
: 로더를 적용할 파일의 확장자를 정규표현식으로 나타낸다.use
: 적용할 로더를 나타내는데, 주의할 점은 오른쪽에서 왼쪽 방향으로 적용 한다는 것이다.
위 예시에선 CSS 파일을 해석하는 css-loader
와 그걸 HTML 파일의 <style>
태그에 삽입해주는 style-loader
를 사용한 경우이다.
resolve
웹팩으로 하여금 특정한 확장자나 디렉토리를 인식하게 해주는 옵션이다.
module.exports = {
resolve: {
modules: ['node_modules'],
extensions: ['.jsx', '.css'],
},
};
modules
: 모듈을 사용하기 위해 상대/절대 경로를 적어주어야 하는데 그 수고를 덜어준다. (참고)extensions
: 확장자를 생략할 수 있게 해준다. (동일한 이름의 다른 확장자가 있다면 먼저 나온게 처리된다.)
plugin
웹팩의 빌드 프로세스를 커스터마이징 할 수 있는 옵션으로 결과물의 형태를 바꾼다고 생각하면 된다.
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
})
],
};
위 예시는 CSS를 별도의 파일로 분리하는 플러그인을 사용한 것이다. 자주 쓰이는 플러그인이며 이것 외에도 여러가지가 있다.
devtool
변환시킨 코드와 원래 코드와의 매핑이 가능하게 하는 sourcemap 에 대한 설정 옵션이다.
module.exports = {
devtool: 'eval',
};
보통 개발단계(development)에선 eval
을, 배포단계(production)에선 hidden-source-map
을 사용한다.
mode
웹팩에 내장된 최적화가 적용되는 여부를 판단하기 위해 제공되는 옵션으로 설정하지 않으면 경고문구가 뜬다.
module.exports = {
mode: 'development',
};
optimization
옵션을 내부적으로 설정하여 개발/배포에 따른 최적화가 이루어진다.
웹팩의 기본 사용법
웹팩을 사용하기 위해선 JS를 브라우저 밖에서도 실행할 수 있는 환경인 Node.js가 설치되어 있어야 하며 패키지 매니저인 npm이나 yarn을 통해서 사용할 수 있다. 먼저 npm init
을 통해서 package.json
파일이 만들어졌다는 가정하에 어떤 흐름으로 웹팩 설정을 하는지 알아보자. 여기선 간단한 리액트 프로젝트를 진행한다 가정하고 Babel을 설치해본다.
웹팩 설치
npm i -D webpack webpack-cli
webpack
은 웹팩의 핵심이 들어있는 패키지이며 webpack-cli
는 웹팩을 CLI에서 실행하게 해주는 패키지이다. 개발할 때만 사용할 것이기 때문에 -D
옵션을 넣어준다.
필요한 loader 및 plugin 설치
npm i -D babel-loader @babel/core @babel/preset-env @babel/preset-react
webpack.config.js 생성
touch webpack.config.js
이 파일이 웹팩의 모든 설정을 관리하는 파일로 패키지인 webpack
이 번들링을 수행할 때 이 설정파일을 보고 한다. 따라서 여기에는 entry
, output
, loader
, plugin
등 필수적인 설정들이 모두 들어있다.
webpack.config.js 설정
const path = require('path');
module.exports = {
mode: 'development',
devtool: 'eval',
resolve: {
extensions: ['.js', '.jsx'],
},
entry: {
app: './App',
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
}
}
]
},
output: {
filename: 'app.js',
path: path.resolve(__dirname, 'dist'),
},
};
Babel을 활용하여 리액트의 JSX를 해석하고 ES6+ 문법을 각 브라우저에 맞게 변환시키는 역할을 하는 로더를 추가하였다.
웹팩 빌드
웹팩을 빌드하는 방법은 크게 2가지가 있다.
npx webpack
: 원래npm
으로 설치된 패키지를 실행하기 위해선 글로벌로 설치된 경우가 아닌 이상package.json
의scripts
옵션을 통해서 실행해야 하지만npm 5.2+
부터 나온npx
를 활용하면 로컬로 설치된 경우도 패키지 명만 입력하면 CLI에서 바로 실행할 수 있다.-
npm run webpack
: 따로 실행 스크립트를 정의해서 실행하는 방식으로package.json
에 아래와 같이 설정된 경우.-
{ "scripts": { "webpack": "webpack", }, }
-