Webpack 완벽 가이드 | 모듈 번들러·Loaders·Plugins·최적화·실전 활용
이 글의 핵심
Webpack으로 모듈 번들링을 구현하는 완벽 가이드입니다. Entry, Output, Loaders, Plugins, Code Splitting, Tree Shaking까지 실전 예제로 정리했습니다.
실무 경험 공유: Webpack 설정을 최적화하면서, 빌드 시간이 70% 단축되고 번들 크기가 50% 감소한 경험을 공유합니다.
들어가며: “빌드가 너무 느려요”
실무 문제 시나리오
시나리오 1: 빌드 시간이 10분이에요
최적화가 안 돼 있습니다. Webpack 설정으로 3분으로 단축합니다.
시나리오 2: 번들 크기가 너무 커요
모든 코드가 포함됩니다. Code Splitting과 Tree Shaking으로 줄입니다.
시나리오 3: 설정이 복잡해요
많은 옵션이 있습니다. 핵심만 이해하면 됩니다.
1. Webpack이란?
핵심 특징
Webpack은 모듈 번들러입니다.
주요 장점:
- 모듈 번들링: 여러 파일을 하나로
- Loaders: 다양한 파일 처리
- Plugins: 강력한 확장
- Code Splitting: 청크 분리
- Tree Shaking: 사용 안 하는 코드 제거
2. 설치 및 기본 설정
설치
npm install -D webpack webpack-cli webpack-dev-server
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
devServer: {
static: './dist',
port: 3000,
hot: true,
},
};
package.json
{
"scripts": {
"build": "webpack --mode production",
"dev": "webpack serve --mode development"
}
}
3. Loaders
CSS Loader
npm install -D style-loader css-loader
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
};
TypeScript Loader
npm install -D ts-loader typescript
module.exports = {
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
};
Image Loader
module.exports = {
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
};
4. Plugins
HtmlWebpackPlugin
npm install -D html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
title: 'My App',
}),
],
};
MiniCssExtractPlugin
npm install -D mini-css-extract-plugin
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
};
5. Code Splitting
Entry Points
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js',
},
output: {
filename: '[name].[contenthash].js',
},
};
Dynamic Import
// src/index.js
button.addEventListener('click', async () => {
const module = await import('./heavy-module.js');
module.doSomething();
});
SplitChunksPlugin
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
priority: 10,
},
common: {
minChunks: 2,
priority: 5,
reuseExistingChunk: true,
},
},
},
},
};
6. 최적화
Production 설정
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
mode: 'production',
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: true,
},
},
}),
new CssMinimizerPlugin(),
],
},
};
Tree Shaking
// package.json
{
"sideEffects": false
}
// webpack.config.js
module.exports = {
mode: 'production',
optimization: {
usedExports: true,
},
};
7. Source Maps
module.exports = {
devtool: 'source-map', // Production
// devtool: 'eval-source-map', // Development
};
8. 환경 변수
npm install -D dotenv-webpack
const Dotenv = require('dotenv-webpack');
module.exports = {
plugins: [
new Dotenv(),
],
};
9. React 통합
npm install -D babel-loader @babel/core @babel/preset-react @babel/preset-env
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
};
10. 실전 예제: 풀 설정
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => {
const isDevelopment = argv.mode === 'development';
return {
mode: argv.mode,
entry: './src/index.tsx',
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
{
test: /\.css$/i,
use: [
isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
optimization: {
minimize: !isDevelopment,
minimizer: [new TerserPlugin()],
splitChunks: {
chunks: 'all',
},
},
devServer: {
static: './dist',
port: 3000,
hot: true,
},
devtool: isDevelopment ? 'eval-source-map' : 'source-map',
};
};
정리 및 체크리스트
핵심 요약
- Webpack: 모듈 번들러
- Loaders: 다양한 파일 처리
- Plugins: 강력한 확장
- Code Splitting: 청크 분리
- Tree Shaking: 사용 안 하는 코드 제거
- 최적화: 빌드 시간, 번들 크기
구현 체크리스트
- Webpack 설치
- 기본 설정
- Loaders 추가
- Plugins 설정
- Code Splitting
- 최적화
- Source Maps
- React/Vue 통합
같이 보면 좋은 글
- Vite 완벽 가이드
- Turborepo 완벽 가이드
- Babel 완벽 가이드
이 글에서 다루는 키워드
Webpack, Bundler, Build Tools, Optimization, JavaScript, TypeScript, Frontend
자주 묻는 질문 (FAQ)
Q. Vite와 비교하면 어떤가요?
A. Webpack이 더 성숙하고 플러그인이 많습니다. Vite는 더 빠릅니다.
Q. 학습 곡선이 높나요?
A. 네, 초반에는 어렵지만 익숙해지면 강력합니다.
Q. CRA 없이 React를 설정할 수 있나요?
A. 네, Webpack으로 직접 설정할 수 있습니다.
Q. 프로덕션에서 사용해도 되나요?
A. 네, 대부분의 대규모 프로젝트에서 사용하고 있습니다.