테마
Webpack: 가장 대표적인 번들러
Webpack은 자바스크립트 애플리케이션을 위한 정적 모듈 번들러로, Entry, Output, Loaders, Plugins, Mode의 5대 핵심 개념을 기반으로 모든 종류의 에셋을 의존성 그래프로 관리하고 번들링한다.
학습 목표
- Webpack의 핵심 역할과 등장 배경을 이해한다
- Webpack의 5대 핵심 개념(Entry, Output, Loaders, Plugins, Mode)을 설명할 수 있다
- Webpack이 다양한 모듈 시스템(CommonJS, ESM, AMD)을 지원하는 방식을 파악한다
- webpack.config.js 기본 설정을 작성할 수 있다
- Module Federation Plugin의 존재와 마이크로프론트엔드에서의 의의를 안다
1. Webpack이란?
Webpack 공식 사이트의 메인 이미지는 다양한 종류의 파일(.js, .ts, .css, .png, .json 등)이 Webpack을 통과하여 정적 에셋(static assets)으로 변환되는 모습을 보여준다. Webpack의 핵심 역할을 한 마디로 요약하면 **"의존 관계가 있는 모듈들을 정적 에셋으로 번들링"**하는 것이다.
1.1 Webpack이 필요한 이유
프론트엔드 개발 역사를 따라가면 번들러가 왜 필요한지 자연스럽게 이해된다.
| 시기 | 방식 | 문제점 |
|---|---|---|
| 초기 | <script> 태그 나열 | 전역 스코프 충돌, 순서 관리 어려움 |
| IIFE 시대 | 즉시 실행 함수로 스코프 분리 | 최적화 어려움, 사용 여부 확인 불가 |
| CommonJS | require()/module.exports | 브라우저 미지원, 동기적 로딩 |
| ES Module | import/export | 브라우저 지원 불완전, 번들링이 여전히 더 효율적 |
| Webpack | 모든 모듈 시스템 지원 + 에셋 번들링 | 설정 복잡성 (이후 도구들이 해결) |
2. Webpack의 5대 핵심 개념
Webpack을 이해하는 데 있어 반드시 알아야 할 5가지 핵심 개념이 있다.
2.1 Entry (진입점)
Entry는 Webpack이 내부 의존성 그래프를 생성하기 위해 사용하는 시작 모듈이다. 이 진입점에서 직접적/간접적으로 의존하는 모든 모듈과 라이브러리를 추적한다.
javascript
// 단일 진입점 (기본값: src/index.js)
module.exports = {
entry: './src/index.js'
};
// 다중 진입점
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js'
}
};2.2 Output (출력)
Output은 생성된 번들을 내보낼 위치와 파일명을 지정한다.
javascript
const path = require('path');
module.exports = {
output: {
filename: '[name].[contenthash].js', // 캐시 버스팅
path: path.resolve(__dirname, 'dist'),
clean: true // 빌드 전 dist 폴더 정리
}
};2.3 Loaders (로더)
Webpack은 기본적으로 JavaScript와 JSON만 이해한다. 로더는 그 외의 파일을 Webpack이 처리할 수 있는 모듈로 변환한다. module.rules에서 test(대상 파일)와 use(적용할 로더)를 쌍으로 정의한다.
javascript
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx|ts|tsx)$/, // 대상 파일
exclude: /node_modules/,
use: 'babel-loader' // 적용할 로더
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'] // 오른쪽에서 왼쪽으로 적용
},
{
test: /\.(png|svg|jpg|gif)$/,
type: 'asset/resource' // Webpack 5 내장 에셋 모듈
}
]
}
};주요 로더:
| 로더 | 역할 |
|---|---|
babel-loader | Babel을 통한 JS/TS 트랜스파일 |
swc-loader | SWC를 통한 고속 트랜스파일 |
ts-loader | TypeScript 컴파일 (타입 검사 포함) |
css-loader | CSS를 JS 모듈로 변환 |
style-loader | CSS를 DOM에 <style> 태그로 주입 |
sass-loader | SCSS/SASS → CSS 변환 |
file-loader | 파일을 출력 디렉토리에 복사 (Webpack 4) |
2.4 Plugins (플러그인)
플러그인은 번들 최적화, 에셋 관리, 환경 변수 주입 등 로더로는 수행할 수 없는 광범위한 작업을 처리한다.
javascript
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { DefinePlugin } = require('webpack');
module.exports = {
plugins: [
new HtmlWebpackPlugin({ template: './src/index.html' }),
new MiniCssExtractPlugin({ filename: '[name].[contenthash].css' }),
new DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') })
]
};주요 플러그인:
| 플러그인 | 역할 |
|---|---|
HtmlWebpackPlugin | HTML 파일 생성, 번들 자동 삽입 |
MiniCssExtractPlugin | CSS를 별도 파일로 추출 |
DefinePlugin | 컴파일 타임 상수/환경변수 정의 |
TerserPlugin | JavaScript 코드 압축 (production 기본 포함) |
CopyWebpackPlugin | 정적 파일을 출력 디렉토리에 복사 |
ModuleFederationPlugin | 마이크로프론트엔드 런타임 모듈 공유 |
2.5 Mode (모드)
Mode는 빌드 환경에 따른 Webpack의 내장 최적화를 활성화한다.
| 모드 | 내장 동작 |
|---|---|
development | 상세한 에러 메시지, 소스맵 활성화, 빠른 리빌드 |
production | Tree Shaking, 코드 압축(TerserPlugin), 최적화 활성화 |
none | 내장 최적화 비활성화 |
3. webpack.config.js 전체 예시
javascript
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.tsx',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js']
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
exclude: /node_modules/,
use: 'swc-loader' // Babel 대신 SWC 사용
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html'
})
],
devServer: {
port: 3000,
hot: true // Hot Module Replacement
}
};4. Module Federation Plugin (개요)
Webpack 5에서 도입된 Module Federation은 런타임에 서로 다른 빌드의 모듈을 공유할 수 있게 해주는 기능이다. 마이크로프론트엔드 아키텍처에서 핵심적인 역할을 한다.
javascript
// 간략 예시 (상세는 챕터 09에서 다룸)
const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
plugins: [
new ModuleFederationPlugin({
name: 'app1',
remotes: { app2: 'app2@http://localhost:3002/remoteEntry.js' },
shared: ['react', 'react-dom']
})
]
};Module Federation의 상세한 내용은 챕터 09: 모듈 페더레이션에서 전용으로 다룬다. 여기서는 Webpack이 마이크로프론트엔드 런타임 통합의 유일한 공식 도구라는 점만 기억하자.
5. Webpack의 장단점
| 장점 | 단점 |
|---|---|
| 가장 넓은 생태계와 플러그인 | 설정이 복잡하다 |
| 모든 모듈 시스템(CJS, ESM, AMD) 지원 | 빌드 속도가 상대적으로 느리다 |
| Module Federation 공식 지원 | 러닝 커브가 높다 |
| HMR, 코드 분할, 지연 로딩 완벽 지원 | 작은 프로젝트에는 과도하다 |
| 거의 모든 프레임워크와 호환 | 초기 설정 보일러플레이트가 많다 |
5.1 성능 개선 전략
| 전략 | 효과 |
|---|---|
babel-loader → swc-loader 교체 | 트랜스파일 속도 10~20배 향상 |
cache 옵션 활성화 (Webpack 5) | 재빌드 시 변경된 모듈만 처리 |
thread-loader 사용 | 멀티 스레드 병렬 처리 |
DllPlugin 활용 | 변경되지 않는 의존성 사전 빌드 |
splitChunks 최적화 | 공통 모듈 분리로 캐시 효율 향상 |
핵심 정리
| 개념 | 핵심 내용 |
|---|---|
| Webpack | 모든 종류의 에셋을 의존성 그래프로 관리하는 정적 모듈 번들러 |
| Entry | 의존성 그래프의 시작점. 기본값 src/index.js |
| Output | 번들 출력 위치와 파일명 지정 |
| Loaders | 비JS 파일을 Webpack이 이해하는 모듈로 변환 |
| Plugins | 번들 최적화, 에셋 관리 등 광범위한 확장 기능 |
| Mode | development/production에 따른 내장 최적화 전환 |
| Module Federation | 마이크로프론트엔드 런타임 모듈 공유 (챕터 09에서 상세) |
다음 단계
- 다음 문서 07-Vite.md에서 ESM 기반 개발 서버와 Rollup 프로덕션 빌드를 결합한 차세대 프론트엔드 도구 Vite의 원리와 사용법을 학습한다.