Webpack(웹팩)은 대표적인 자바스크립트 모듈 번들러(Module Bundler)로, 많은 기능과 확장성으로 좀 더 복잡한 프로젝트에서도 효율적으로 모듈을 관리할 수 있도록 도와줍니다.
여기서 말하는 Module Bundler란 분리된 코드 조각(파일)들을 하나로 묶는 도구를 말합니다.
Webpack이 애플리케이션을 처리할 때, 내부적으로는 프로젝트에 필요한 모든 모듈을 매핑하고 하나 이상의 번들을 생성하는 의존성 그래프(Dependency Graph)를 만듭니다.
Webpack에서의 Dependency Graph(의존성 그래프)란?
프로젝트의 소스 코드와 해당 코드 간의 의존 관계를 시각적으로 나타낸 구조를 말합니다. 이 그래프는 프로젝트 내에서 어떤 파일이 다른 파일에 의존하고 있는지, 즉 어떤 파일이 다른 파일을 import 또는 require하고 있는지를 표현합니다.
Webpack은 이러한 의존성 그래프를 분석하여 필요한 자원들을 번들로 묶어주는 역할을 수행합니다. 그래프 상에서 시작점으로부터 모든 의존성을 추적하고, 각 의존성에 대한 모듈 번들을 생성하여 최종적으로 하나 이상의 번들 파일을 생성합니다. 이를 통해 웹 애플리케이션의 성능을 최적화하고 로딩 속도를 향상시킬 수 있습니다.
정리하면, 의존성 그래프는 소프트웨어의 모듈 간 상호작용을 시각화한 구조로, 이를 기반으로 Webpack은 효율적으로 번들링을 수행합니다.
⚙️ Webpack 호환 버전
Webpack은 ES5가 호환되는 모든 브라우저를 지원합니다(IE8 이하는 지원되지 않습니다).
Webpack 5 기준 Node.js 버전 10.13.0 이상에서 실행됩니다.
package.json 파일 생성: $ npm init -y
webpack 설치: $ npm install -D webpack webpack-cli webpack-dev-server
webpack
: 모듈(패키지) 번들러의 핵심 패키지입니다.webpack-cli
: 터미널에서 Webpack 명령(CLI)을 사용할 수 있습니다.webpack-dev-server
: 개발용으로 Live Server를 실행(HMR), 애플리케이션 코드에 변경이 발생하면 브라우저를 새로 고치지 않고도 모듈 단위로 변경된 부분만 업데이트할 수 있도록 하는 HMR을 지원합니다. 이를 통해 애플리케이션을 다시 빌드하거나 브라우저를 새로고침할 필요 없이 수정된 코드를 빠르게 확인할 수 있습니다.webpack을 실행할 때 아래와 같은 방법들이 있습니다.
cli
명령어로 실행시키는 방법package.json
파일에서 명령어 스크립트 직접 작성하는 방법webpack.config.js
파일에서 세부적인 옵션 작성하는 방법1. cli 명령어로 실행시키는 방법
npx
명령어를 이용하여 실행시킬 수 있습니다.$ npx webpack --entry ./src/index.js --output-path ./dist
cf.
src
폴더에는 개발 시 작성되는소스 코드(source code)
를,dist
폴더에는 빌드 과정을 거쳐 배포할배포 코드(distribution code)
를 생성하기 위해 두 코드의 경로를 분리합니다.
2. package.json 파일에서 직접 작성하는 방법
package.json
에 명시할 수 있습니다.{
"scripts": {
"build": "webpack --mode=none --entry=src/index.js --output=dist/bundle.js"
}
}
3. webpack.config.js 파일에서 세부 옵션 작성하는 방법
webpack.config.js
파일을 프로젝트 루트(Root) 경로에 생성하고 내부에 세부적인 옵션들을 작성합니다. (cf. 브라우저가 아닌 Node.js 환경에서 실행되기 때문에 CommonJS 모듈 방식으로 작성합니다.)package.json
에서 webpack을 실행할 스크립트를 작성하면 webpack.config.js
파일에서의 설정대로 webpack이 실행됩니다.// webpack.config.js
module.exports = {
mode: 'none',
entry: './src/index.js',
output: './dist/bundle.js'
};
// package.json
{
"scripts": {
"dev": "webpack serve --mode development --open",
"build": "webpack --mode production"
}
}
Webpack은 webpack.config.js
파일을 통해 프로젝트의 구성(Configuration)을 설정합니다.
구성 옵션에는 기본적으로 Entry
, Output
, Loader
, Plugin
, Mode
가 있습니다.
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js', // 진입점
output: {
path: path.resolve(__dirname, 'dist'), // 번들 파일 생성 경로
filename: 'bundle.js', // 번들 파일명
},
module: { // 로더(모듈)
rules: []
},
plugins: [], // 플러그인
// 기타 옵션...
};
엔트리 포인트(진입점)는 프로젝트의 소스 파일 진입점(경로)을 설정하는 것으로, webpack이 내부의 디펜던시 그래프 를 생성하기 위해 사용해야 하는 모듈, 시작 지점입니다.
기본적으로 entry point는 하나로 지정하지만 필요하다면 여러 진입점을 지정할 수도 있습니다.
// webpack.config.js
module.exports = {
entry: './src/index.js',
};
배포할 파일(번들된 파일)이 출력(생성)될 경로 및 파일명을 지정하는 속성입니다.
// webpack.config.js
module.exports = {
output: {
path: '/dist', // 출력 경로
filename: 'bundle.js' // 파일명
}
};
Webpack은 기본적으로 JavaScript와 JSON 파일만 해석이 가능하지만 로더를 사용하여 다른 유형의 파일(CSS, 이미지 등)을 처리할 수 있도록 모듈(module)로 변환합니다. 로더는 주로 파일의 형식을 변경하거나 특정 작업을 수행하기 위해 사용됩니다.
로더를 사용하기 위해서는 사용할 패키지를 설치하고 module.rules
속성에 Array 형태로 작성하며, 기본적으로 test
와 use
속성을 가집니다.
test
: 변환이 필요한 파일(들)을 식별하는 속성으로 정규표현식(RegExp)으로 작성하여 일치하는 파일을 변환할 수 있도록 지정합니다.use
: 변환을 수행하는데 사용되는 로더를 가리키는 속성입니다. // webpack.config.js
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(js|jsx|ts|tsx)$/i,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-typescript',
['@babel/preset-react', { runtime: 'automatic' }],
]
}
}
},
]
}
};
위 예시 코드에서는 Style Loader, CSS Loader와 Babel Loader를 사용하였습니다.
위 로더 이외에도 여러가지가 있습니다. (Sass Loader, File Loader, TS Loader, SWC Loader 등)
🗂️ 적용한 패키지 설명
1. CSS Loader & Style Loader
$ npm install -D style-loader css-loader
css-loader
: CSS 파일을 로드하는 데 사용됩니다.style-loader
: CSS loader로 로드한 CSS 코드를 HTML에 style 태그로 넣어주는 역할을 합니다. ⚠️ 로더 적용 순서 주의
특정 파일에 대해 여러 개의 로더를 사용하는 경우 로더가 적용되는 순서에 주의해야 합니다. 로더는 기본적으로 역순(뒷쪽에서 앞쪽 순으로)으로 적용됩니다.따라서 css-loader가 먼저 실행되고 style-loader가 후에 실행되어야 하므로 로더 적용 순서는
use: ['style-loader', 'css-loader']
로 역순 배치해야 합니다.만약 SCSS, Sass과 같은 스타일 전처리기를 사용한다면 sass-loader가 제일 먼저 전처리(scss혹은 sass 파일을 css 파일로 변환)한 다음에 css-loader를 적용해야 합니다. 즉, 적용 순서는 역순으로
use: ['style-loader', 'css-loader', 'sass-loader]
가 됩니다.
2. Babel Loader
$ npm install -D babel-loader @babel/core @babel/preset-env
babel-loader
: Babel이 JavaScript 코드를 트랜스파일하는 과정을 Webpack에 통합시켜주는 로더입니다.@babel-core
: Babel의 핵심 모듈로, JavaScript 코드를 AST(abstract syntax tree)로 파싱하고, 트랜스파일링된 코드를 생성하는 등의 핵심적인 기능을 제공합니다.@babel/preset-env
: preset은 plugin들을 모아놓은 것으로, 대상(target) 환경에 맞춰 자동으로 필요한 구문 변환(syntax transform)을 합니다. 최신 JavaScript 기능을 지원하고 브라우저 호환성을 고려하여 필요한 트랜스파일링을 수행합니다.@babel/preset-typescript
: TypeScript를 트랜스파일링하기 위해 사용됩니다.@babel/preset-react
: React의 JSX를 트랜스파일링하며, JSX 코드를 React.createElement 함수 호출 코드로 변환하여 React 엘리먼트를 생성합니다. 옵션으로 추가한, { runtime: 'automatic' }
객체는 import React from 'react'
를 자동으로 추가하는 기능입니다.번들링된 결과물을 처리하는 역할의 외부 플러그인을 연결할 수 있습니다. 플러그인을 통해 번들 최적화, 애셋 관리, 환경 변수 주입, 파일 복사 등 다양한 작업을 수행하는 도구로 활용할 수 있습니다.
플러그인을 사용하려면 require
키워드를 통해 플러그인을 가져오고 plugins
배열에 추가해야 합니다. 다른 목적으로 플러그인을 여러 번 사용하도록 설정할 수 있으므로 new
연산자로 호출하여 플러그인의 인스턴스
를 만들어야 합니다.
// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "index.html",
}),
new CleanWebpackPlugin(),
new CopyWebpackPlugin({
patterns: [
// from: 복사할 파일 경로와, to: 붙여 넣을 대상 경로
{ from: "public/images", to: "assets/images" },
,
],
}),
]
};
위 예시에 사용된 플러그인 설명 (추천 플러그인 3개)
html-webpack-plugin
: 생성된 모든 번들을 자동으로 삽입하여 HTML 파일을 생성합니다.template
속성: 웹팩이 사용할 HTML 템플릿 파일의 경로를 설정filename
속성: 생성될 HTML 파일의 이름을 설정합니다. CleanWebpackPlugin
: 빌드 시점에서 이전에 빌드했던 결과물을 자동으로 삭제합니다. 다양한 옵션이 존재하니 프로젝트에 맞게 설정 가능합니다.CopyWebpackPlugin
: 빌드 시점에 웹팩으로 빌드한 결과물 외에, 원하는 파일들을 추가로 복사할 수 있습니다. 예를 들어 프로젝트의 public 폴더 내의 Assets(이미지, 문서 등의 정적 자원들)와 파일들 또는 전체 디렉터리를 빌드 디렉터리에 복사할 수 있습니다.patterns
속성: 복사할 파일 경로(from)와 붙여넣을 대상 경로(to)를 객체로 설정합니다. 여기서의 경로는 상대 경로로, Webpack의 Outputs(출력) 경로를 기준으로 합니다. 따라서 번들 파일의 path를 /dist
라고 했을때, { from: "public/images", to: "assets/images" }
는 /public/images
폴더 내부의 파일들을 /dist/assets/images
위치로 복사한다는 의미입니다. Webpack에서 자체적으로 제공하는 플러그인이 아닌 경우 별도로 설치 후 사용할 수 있습니다.
Webpack의 기본 플러그인들의 목록은 Webpack 플러그인 목록에서 확인하실 수 있습니다.
모드 설정을 통해 Webpack에 내장된 환경별 최적화를 활성화할 수 있습니다.
production
: 배포 환경으로 설정(기본값)development
: 개발 환경으로 설정none
: 기본 최적화 옵션에서 제외// webpack.config.js
module.exports = {
mode: 'development' // 또는 'production' 또는 'none'
};
entry
: 웹팩 번들링의 시작점으로 지정된 파일을 가리키며, 의존성 그래프를 구성하여 번들을 생성합니다.output
: 웹팩 번들링 결과물의 출력 경로와 파일 이름을 설정하는 옵션입니다.loader
: JS, JSON 파일을 포함하여 그 외의 파일의 형식을 해석하여 변경하거나 특정 작업을 수행하기 위해 사용됩니다.plugin
: 웹팩 빌드 프로세스에 추가적인 기능을 제공하는 도구로, 번들 최적화, 환경 변수 주입, 파일 복사 등 다양한 작업을 수행합니다.mode
: 개발 또는 프로덕션 환경에서 웹팩의 빌드 모드를 설정하는 옵션으로, 'development', 'production', 'none' 중 하나를 선택하여 해당 환경에 맞게 최적화 수준을 설정합니다.이처럼 웹팩의 핵심 개념들을 위주로 정리해 보았습니다. 이외에도 세부적으로 조절 가능한 옵션이 다양하기 때문에 프로젝트를 진행 시 필요한 부분들은 추가로 찾아가며 적용하는 것이 좋겠습니다.
모듈 번들러는 Webpack 말고도 Vite, Rollup, Parcel 등 사용할 수 있는 도구는 여러 가지가 있습니다.
빠른 개발 속도를 제공한다는 Vite, 다양한 Loader와 Plugin 적용이 가능한 Webpack 등 번들러마다 각각의 장단점이 있을 수 있으니 프로젝트의 규모나 요구사항을 고려하여 선택하면 되겠습니다.
Reference.