웹팩 기본 사용법 (1)
처음 접해보는 웹팩의 원리와 기본 사용 방법
2023-11-30
웹팩(기본)배경
-
웹팩은 모던 javascript 어플리케이션을 위한 정적 모듈 번들러이다. 번들러는 웹팩 이외에도 다양한게 있는데 (rollup , esbuild , vite , parcel 등) 웹팩이 가장 오래되었기도하고 많이 사용하고 있기 때문에 이번 기회에 배워보기로 했다.
-
Javascript에서 문법 수준에서 모듈을 지원하기 시작한것은 ES2015부터 이다. import/export 구문이 없었던 이전 상황에서는 하나의 함수를 만들었을 때 전역 공간에 노출되어 버그나 오류를 발생시킬 수 있었다.
예를들어 아래와 같은 덧셈 함수는
// math.js
function add(a,b){
return a+b;
}
// app.js
add(10,20);
모두 하나의 HTML 파일안에서 로딩해야만 실행된다. math.js가 로딩되면 app.js는 add 함수를 찾고 실행시키는데, add 함수가 전역으로 사용되기 때문에 다른 파일에서 같은 이름의 함수를 사용하면 충돌이 발생할 수 있다.
이런 문제를 예방하기위해 IIFE(즉시실행함수) 방식의 스코프를 사용했다.
var math = math || {}
;(function () {
function add(a, b) {
return a + b
}
math.add = add
})();
함수 스코프를 만들어 외부에서 접근할 수 없도록해 충돌을 막을 수 있었고, 전역에 선언한 math라는 이름만 사용하면 된다.
자바스크립트 모듈을 구현하는 대표적인 명세는 AMD와 CommonJS가 있다.
- AMD(Asynchronous Module Definition)는 비동기 방식으로 모듈을 로딩한다. 브라우저 환경에서 주로 사용된다.
- UMD(Universal Module Definition)는 AMD와 CommonJS를 지원하는 모듈을 만들기 위해 사용된다.
- CommonJS는 export로 모듈을 만들고 require()함수로 import하는 방식이다. 주로 서버 사이드 플랫폼인 Node.js 환경에서 주로 사용된다.
CommonJS
//math.js
export function add(a,b){
return a+b;
}
//app.js
const math = require('./math.js');
math.add(10,20);
ES2015 표준 모듈 시스템
//math.js
export function add(a,b){
return a+b;
}
//app.js
import {add} from './math.js';
add(10,20);
export
구문으로 모듈을 만들고 import
구문으로 가져올 수 있다.
이러한 방식은 모든 브라우저에서 지원하지 않는다. 따라서 웹팩과 같은 모듈 번들러를 사용해야한다.
웹팩사용방법
웹팩은 여러개의 파일을 하나로 합쳐주는 번들러(bundler)이다. 웹팩을 사용하면 자바스크립트뿐만 아니라 css, html, 이미지 등 모든 파일을 모듈로 관리할 수 있다.
웹팩으로 간단하게 작업을 해보자.
먼저 웹팩과 웹팩 터미널 도구인 cli를 설치한다.
npm install -D webpack webpack-cli
root 디렉토리에 webpack.config.js
파일을 생성한다.
//webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: '[name].js',
path: path.resolve(__dirname, './dist'),
},
};
mode
는 웹팩의 모드를 설정한다.development
로 설정하면 개발용으로,production
으로 설정하면 배포용으로 빌드된다.entry
는 웹팩이 빌드할 파일인 진입점을 지정한다.output
은 웹팩이 빌드한 결과물을 저장할 경로와 파일명을 지정한다.- [name]은 entry에 지정한 파일명을 그대로 사용한다.
- [hash]는 웹팩이 빌드할 때마다 고유한 해시값을 붙여준다.
package.json에 빌드 스크립트를 추가한다.
//package.json
{
"scripts": {
"build": "webpack"
}
}
이제 npm run build
명령어를 실행하면 웹팩이 빌드를 시작한다.
웹팩 로더
웹팩은 자바스크립트 파일 뿐만 아니라 css, html, 이미지 등 모든 파일을 모듈로 관리할 수 있다. 하지만 웹팩은 자바스크립트 파일만 이해할 수 있기 때문에 css나 html, 이미지 파일을 자바스크립트 파일로 변경해야한다. 이때 사용하는 것이 로더이다.
자주 사용하는 로더
- css-loader : css 파일을 자바스크립트 파일로 변경한다.
- style-loader : 자바스크립트로 변경된 스타일을 동적으로 돔에 추가해준다. 주로 css-loader와 함께 사용한다.
- file-loader : 파일을 모듈로 사용할 수 있게 url 경로를 변경한다.
- url-loader : 파일을 모듈로 사용할 수 있게 url 경로를 변경하고 파일을 base64로 인코딩한다.
css-loader
npm install -D css-loader
웹팩은 모두 모듈로 바라보기 때문에 자바스크립트 뿐만 아니라 스타일시트도 import 구문으로 불러올 수 있다.
import './style.css';
// style.css
body {
background-color: red;
}
//webpack.config.js
module.exports = {
{...}
module: {
rules: [
{
test: /\.css$/, // .css 확장자로 끝나는 모든 파일
use: ["css-loader"], // css-loader를 적용한다
},
],
},
};
웹팩은 entry에서 모듈을 검색하다가 css 파일을 찾으면 css-loader를 적용한다.
style-loader
모듈로 변경된 스타일 시트는 돔에 추가되어야 브라우저가 해석한다. css-loader는 css 파일을 자바스크립트 파일로 변경할 뿐 돔에 추가하지는 않는다. 따라서 style-loader를 추가해야한다.
npm install -D style-loader
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
};
style-loader를 css-loader보다 앞에 적용한다. 로더는 배열로 설정하면 뒤 -> 앞 순서대로 로더가 작동한다.
file-loader
css 뿐만 아니라 소스코드에서 사용하는 모든 파일들을 모듈로 사용할 수 있게 할 수 있다.
npm install -D file-loader
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i, // i는 대소문자 구분없이, 확장자들
loader: "file-loader",
options: {
publicPath: "./dist/", // prefix를 아웃풋 경로로 지정
name: "[name].[ext]?[hash]", // 파일명 형식
},
},
],
},
};
옵션으로 경로를 지정할 수 있다. publicPath
는 파일을 참조하는 경로를 지정한다. name
은 파일명 형식을 지정한다.
url-loader
파일을 base64로 인코딩하여 문자열 형태로 변환한다. 파일 크기가 작은 파일들은 문자열로 변환하여 파일을 요청하는 횟수를 줄일 수 있다.
npm install -D url-loader
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
loader: "url-loader",
options: {
publicPath: "./dist/",
name: "[name].[ext]?[hash]",
limit: 5000, // 5kb 미만 파일만 data url로 처리
},
},
],
},
};
file-loader와 url-loader는 v5부터 기본적으로 제공하며, asset
이라는 키워드로 사용할 수 있다.
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
type: "asset/resource", // file-loader
generator: {
filename: "[name][ext]?[hash]", // [name]은 파일명, [ext]는 확장자
},
},
{
test: /\.(png|jpe?g|gif)$/i,
type: "asset/inline", // url-loader
generator: {
filename: "[name][ext]?[hash]",
},
},
{
test: /\.(png|jpe?g|gif)$/i,
type: "asset", // 기본값은 8kb 미만은 inline, 8kb 이상은 resource
generator: {
filename: "[name][ext]?[hash]",
},
},
],
},
};
웹팩 플러그인
로더는 파일을 해석하고 변환하는 과정에 관여하지만 플러그인은 해당 결과물의 형태를 바꾸는 역할을 한다. 로더는 파일 단위로 처리하는 반면 플러그인은 번들된 결과물을 처리한다. 번들된 자바스크립트를 난독화 한다거나, 특정 텍스트를 추출할 수 있는 용도로 사용한다.
자주 사용하는 플러그인
- BannerPlugin : 결과물에 빌드 정보나 버전같은 정보를 추가할 수 있다.
- DefinePlugin : 환경변수를 설정한다.
- HtmlWebpackPlugin : HTML 파일을 후처리한다.
- CleanWebpackPlugin : 이전 빌드 결과물을 제거한다.
- MiniCssExtractPlugin : CSS 파일을 별도로 추출한다.
BannerPlugin
const webpack = require("webpack");
module.exports = {
plugins: [
new webpack.BannerPlugin({
banner: () => `빌드 날짜: ${new Date().toLocaleString()}`,
}),
],
};
DefinePlugin
개발환경과 운영환경으로 나누어서 작업할 때 환경변수를 설정할 수 있다. 환경에 의존적인 정보를 소스가 아닌 환경 변수로 관리하면 소스코드를 더욱 안전하고 편리하게 관리할 수 있다.
const webpack = require("webpack");
module.exports = {
plugins: [
new webpack.DefinePlugin({
VERSION: JSON.stringify("v.1.2.3"),
PRODUCTION: JSON.stringify(false),
MAX_COUNT: JSON.stringify(999),
"api.domain": JSON.stringify("http://dev.api.domain.com"),
}),
],
};
HtmlWebpackPlugin
npm install -D html-webpack-plugin
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: 'index.js',
output: {
path: path.resolve(__dirname, './dist'),
filename: 'index_bundle.js',
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html", // 템플릿 경로를 지정
minify:
process.env.NODE_ENV === "production"
? {
// 빌드 모드가 production일 때만 사용
collapseWhitespace: true, // 빈칸 제거
removeComments: true, // 주석 제거
}
: false,
}),
],
};
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>webpack App</title>
</head>
<body>
<script src="index_bundle.js"></script>
</body>
</html>
script 태그에 번들링된 결과물을 자동으로 추가해준다. 웹팩 엔트리가 여러개일 경우 여러개의 script 태그를 추가해준다.
CleanWebpackPlugin
npm install -D clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
plugins: [new CleanWebpackPlugin()],
};
MiniCssExtractPlugin
스타일 시트가 점점 많아짐에 따라 하나의 자바스크립트로 만들면 부담이 될 수 있다. 번들 결과물에서 스타일시트 코드만 따로 분리하여 별도의 css파일로 만들어주는 플러그인이다.
npm install -D mini-css-extract-plugin
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
};
운영 환경에서는 MiniCssExtractPlugin.loader
를 사용해 스타일시트를 별도의 파일로 분리한다. 개발 환경에서는 style-loader
를 사용해 동적으로 돔에 추가한다.
웹팩의 로더와 플러그인의 원리, 사용방법에 대해서 알아보았다.
우리가 편리하고 쉽게 사용하는 Create-React-App는 웹팩으로 빌드된 결과물을 제공해준다. 하지만 기본적인 웹팩으로 설정되어있고, 직접 커스텀하려면 eject를 해야한다.
이번 기회에 웹팩의 원리와 기본적인 사용방법을 알아보았다.