Webpack
Webpack
은 가장 오래된 번들러 중 하나로, 여러 파일을 묶어주는 데 매우 강력한 도구입니다. 설정이 다소 복잡할 수 있지만, 확장성과 성능 면에서 매우 안정적입니다. Webpack
은 복잡한 애플리케이션에서도 안전하게 code splitting
을 해주며, 트리셰이킹 기능을 통해 불필요한 코드를 제거할 수 있습니다.설정이 다소 복잡할 수 있지만, 커뮤니티가 크고 레퍼런스가 많아 안정적인 선택이 될 수 있습니다.
주요 특징
- JS 이외의 파일 처리: CSS, 이미지 파일과 같은 JS 이외의 파일들을 처리하려면 별도의
loader
가 필요합니다. 예를 들어,style-loader, css-loader
등을 사용해 CSS 파일을 처리할 수 있습니다. - 안전한 Code Splitting:
Parcel
이나Rollup
보다 코드 스플리팅의 안전성이 높아 복잡한 의존성 트리에서도 안정적으로 번들을 나눌 수 있습니다. - Webpack Dev Server:
webpack-dev-server
를 사용해 실시간으로 개발 환경에서 코드 변경을 반영하고, 자동으로 브라우저를 새로고침할 수 있습니다. - 역사가 깊고 안정적:
Webpack
은 오랜 역사를 가진 번들러로, 많은 서드파티 플러그인과 레퍼런스를 통해 안정적인 사용이 가능합니다. - Tree-shaking 지원: Webpack은 트리셰이킹을 통해 사용하지 않는 코드를 제거할 수 있지만, ES6 모듈에서만 작동합니다.
package.json
의{ sideEffects: false }
항목을 통해side effects
가 없는 코드를 명시적으로 알려줘야 불필요한 코드가 제거됩니다. - 복잡한 애플리케이션에 적합: Webpack은 많은 서드파티 플러그인을 필요로 하며, 복잡한 애플리케이션에서 활용하기 적합합니다.
예시 코드
아래는 Webpack을 사용하여 JS, CSS, 이미지 파일을 번들링하는 예시입니다. 이 예시는 기본적인 설정을 포함하고 있습니다.
// webpack.config.js
const path = require('path');
module.exports = {
mode: 'production', // 'development' 또는 'production' 모드를 선택
entry: './src/index.js', // 엔트리 파일 설정
output: {
filename: 'bundle.js', // 출력 파일 이름
path: path.resolve(__dirname, 'dist'), // 출력 파일 경로
clean: true, // 기존 번들 파일을 제거하고 새로 생성
},
module: {
rules: [
{
test: /\.css$/, // CSS 파일을 처리하는 룰
use: ['style-loader', 'css-loader'], // style-loader와 css-loader 사용
},
{
test: /\.(png|svg|jpg|gif)$/, // 이미지 파일을 처리하는 룰
type: 'asset/resource', // 파일을 별도의 리소스로 처리
},
],
},
optimization: {
splitChunks: {
chunks: 'all', // 코드 스플리팅 설정
},
usedExports: true, // 사용되지 않는 export 제거 (트리셰이킹)
},
};
Tree-shaking 적용 방법
tree-shaking
을 적용하려면 ES6 모듈을 사용해야 하며, package.json
에서 side effects
를 명시해야 합니다. 이를 통해 Webpack
은 불필요한 코드를 안전하게 제거할 수 있습니다.
// package.json
{
"name": "my-webpack-project",
"version": "1.0.0",
"main": "index.js",
"sideEffects": false, // 트리셰이킹 적용을 위한 설정
"dependencies": {
// 프로젝트 의존성 목록
}
}
Webpack Dev Server 설정
개발 환경에서 실시간 반영을 위해 webpack-dev-server
를 설정할 수 있습니다. 아래 예시는 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'),
},
devServer: {
contentBase: path.resolve(__dirname, 'dist'), // 개발 서버의 기본 경로
compress: true, // 파일 압축
port: 9000, // 서버 포트 번호
hot: true, // 핫 리로딩(HMR) 지원
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
};
Parcel
Parcel은 설정 없이 바로 사용할 수 있는 zero-configuration
번들러로, 간편함과 빠른 빌드 속도로 주목받고 있습니다.
Rust
로 작성된 강력한 컴파일러를 기반으로 하여 개발 속도를 크게 향상시키며, 다양한 파일 형식을 플러그인 없이 기본적으로 처리할 수 있는 것이 큰 장점입니다.
주요 특징
-
zero-configuration: Parcel의 가장 큰 장점 중 하나는 별도의 설정 없이 바로 사용할 수 있다는 점입니다. 개발자가 따로 번들링을 위한 설정을 작성할 필요 없이, 기본적인 JS, CSS, HTML, 이미지 파일 등 대부분의 파일을 자동으로 처리합니다. 이는 프로젝트를 시작할 때 빠르게 설정을 끝내고 개발에 집중할 수 있게 도와줍니다.
-
빠른 빌드 속도: Parcel은 성능 최적화를 위해 Rust로 작성된 JS 컴파일러와 CSS transformer, sourcemap 기능을 제공합니다. 특히, SWC(또한 Rust 기반)를 활용하여 ES6 및 CommonJS 모듈에 대해 트리셰이킹과 핫 리로딩(HMR)을 지원합니다.
병렬 빌드
: 워커 쓰레드를 사용하여 여러 작업을 동시에 처리할 수 있어 빠른 빌드를 제공합니다.캐싱 기능
: 모든 빌드 단계(트랜스포메이션, 의존성 해결, 번들링, 최적화 등)가 캐시되며, 코드가 바뀌면 부분적으로만 캐시가 무효화되기 때문에 빠른 빌드를 유지합니다. 이는 Webpack보다 최대 20배 빠른 속도를 제공합니다.
-
다양한 파일 형식 기본 지원: Parcel은 플러그인 없이도 JS, CSS, HTML, 이미지 파일 등 다양한 파일 형식을 기본적으로 지원합니다. 별도의 loader 없이도 파일들을 처리할 수 있기 때문에, 설정이 간편합니다. HTML 파일을 직접 읽어서 JS 엔트리포인트를 지정할 필요도 없습니다.
-
트랜스파일러 기본 지원: Parcel은 Babel, PostCSS, PostHTML 같은 트랜스파일러들을 기본으로 지원합니다.
.babelrc, .postcssrc
같은 설정 파일을 프로젝트 루트에 추가하면 Parcel이 이를 자동으로 인식해 변환 작업을 수행합니다. 심지어node_modules
폴더에 있는 모듈까지도 변환해줍니다. -
동적 import와 코드 스플리팅: Parcel은 동적 import를 사용해 번들을 자동으로 분할할 수 있습니다. 초기 로드 시 필요한 것들만 로드하도록 설정할 수 있으며, 개발 환경에서는 브라우저에서 요청이 있을 때까지 번들링을 지연할 수 있습니다. 이로 인해 실제 필요한 페이지만 로드되며,
dev server
실행 시간을 줄여줍니다. -
핫 모듈 리플레이스먼트(HMR): Parcel은 HMR(Hot Module Replacement)을 기본으로 지원합니다. 코드 수정 사항이 발생할 때 전체 페이지를 다시 로드하지 않고도 변경된 모듈만 교체할 수 있습니다. 특히
React
와Vue
같은 프레임워크와 함께 사용할 때Fast Refresh
기능을 통해 더욱 빠른 피드백을 받을 수 있습니다. -
프로덕션 자동 최적화: Parcel은 프로덕션 빌드 시 여러 가지 최적화 작업을 자동으로 수행합니다.
- Tree Shaking: 사용되지 않는 코드와 CSS 모듈, 동적 모듈 import 등을 자동으로 제거합니다.
- 최소화 및 난독화: JS, CSS, HTML, SVG 파일을 자동으로 최소화(minification)하고 난독화하여 파일 크기를 줄입니다.
- 이미지 최적화: 이미지 파일도 최적화하여 빠른 로딩을 지원합니다.
-
코드 스플리팅: 여러 파트에서 동일한 모듈을 사용하고 있는 경우, Parcel은 해당 모듈을 자동으로 별도의 번들로 분리하여 공통 번들로 만들어줍니다. CSS도 마찬가지로 지원되어, 중복된 CSS가 여러 파일에 포함되지 않도록 최적화할 수 있습니다.
-
브라우저 캐시를 위한 Content Hash 제공: Parcel은 모든 output 파일에 대해
content hash
를 제공하여 브라우저 캐시에 유리합니다. 이를 통해 배포된 파일이 수정되었을 때 캐시가 자동으로 무효화되고, 사용자가 최신 버전의 파일을 받아볼 수 있게 됩니다.
Parcel 예시 코드
Parcel을 사용하는 예시 코드는 매우 간단합니다. 별도의 설정 파일 없이 package.json
파일에서 간단한 명령어만 추가하면, Parcel이 알아서 설정을 처리해줍니다.
// package.json
{
"scripts": {
"dev": "parcel index.html", // 개발 서버 실행
"build": "parcel build index.html" // 프로덕션 빌드
},
"devDependencies": {
"parcel": "^2.0.0"
}
}
주요 파일 구조
Parcel은 기본적으로 HTML 파일을 진입점으로 사용하며, 별도의 엔트리 포인트 설정이 필요하지 않습니다. 아래는 Parcel을 사용하는 프로젝트의 기본 파일 구조입니다.
├── src/
│ ├── index.js # JS 파일
│ ├── style.css # CSS 파일
├── index.html # HTML 파일 (진입점)
└── package.json # Parcel 관련 명령어 포함
Rollup
Rollup은 ES6 모듈(ESM)을 기본으로 지원하며, 매우 깔끔하고 최적화된 번들링 결과물을 생성하는 번들러입니다. 주로 Tree-Shaking
을 통해 사용하지 않는 코드를 제거하고, 여러 모듈을 하나의 파일로 합치는 데 강점을 보입니다. Rollup은 간단한 설정으로도 매우 효율적인 번들링을 제공하지만, JS 이외의 파일을 처리하거나 개발 서버 및 HMR을 사용하려면 플러그인이 필요합니다.
주요 특징
- ES6 모듈 형식 지원: Rollup은 ES6 모듈(ESM) 형식으로 빌드 결과물을 생성합니다. Webpack이 기본적으로 CommonJS 형태만을 지원하는 반면, Rollup은 모던 자바스크립트 모듈 형식을 사용해 더 효율적으로 코드를 관리할 수 있습니다.
- 단일 모듈로 최적화된 코드 생성: Rollup은 여러 개의 모듈을 하나의 단일 모듈로 결합해 최적화된 코드를 생성합니다. 번들링 과정에서 모든 코드를 동일한 수준으로 호이스팅하여 한 번에 처리하므로, 중복된 코드를 효과적으로 제거할 수 있습니다. 이는 특히
code splitting
과 중복 제거에 강점을 보이며, Webpack의ModuleConcatenationPlugin
과 비슷한 역할을 합니다. - 기본 Tree Shaking 지원: Rollup은 사용되지 않는 코드를 제거하는 트리셰이킹 기능을 기본으로 제공합니다. 자바스크립트 외의 파일을 처리할 때도 플러그인을 사용하여 코드를 정적으로 분석하고, 미사용 코드를 제외합니다. 이를 통해 번들의 크기를 최소화할 수 있습니다.
- 개발 서버 및 HMR: Rollup은 기본적으로 개발 서버나 핫 모듈 리플레이스먼트(HMR)를 제공하지 않습니다. 하지만 추가 플러그인을 설치하면 라이브 리로딩과 HMR을 사용할 수 있습니다. 예를 들어,
rollup-plugin-serve
로 개발 서버를 설정하고rollup-plugin-livereload
로 라이브 리로딩을 구현할 수 있습니다. - 해시 캐스캐이딩이 약함: Rollup은 파일의 해시가 변경되면 그 파일을 참조하는 다른 파일들의 해시도 자동으로 변경되는 해시 캐스캐이딩 기능이 약합니다. 이는 번들링 과정에서 캐싱이나 파일 무결성 보장 측면에서 다소 불리할 수 있습니다.
- CommonJS 의존성 및 서드파티 라이브러리 통합: Rollup은 ES6 모듈을 기본으로 사용하기 때문에 CommonJS 모듈과의 호환성에서 제약이 있을 수 있습니다. 이를 해결하기 위해
@rollup/plugin-commonjs
플러그인을 사용하는 경우가 많습니다. 또한, 서드파티 라이브러리와의 통합이 Webpack보다 다소 어려울 수 있습니다. 하지만 필요한 플러그인들을 적절히 활용하면 충분히 해결 가능한 문제입니다.
예시 코드
아래는 Rollup을 사용하여 기본적인 ES6 모듈을 번들링하는 예시입니다. Tree-Shaking 기능을 활용하고, CommonJS 모듈을 처리하는 플러그인도 함께 사용합니다.
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
export default {
input: 'src/index.js', // 진입점 설정
output: {
file: 'dist/bundle.js', // 번들링된 결과물 파일
format: 'esm', // ES6 모듈 형식으로 출력
sourcemap: true, // 디버깅을 위한 소스맵 생성
},
plugins: [
resolve(), // node_modules에서 모듈을 불러오기 위한 플러그인
commonjs(), // CommonJS 모듈을 ES 모듈로 변환하는 플러그인
terser(), // 번들을 최소화하여 최적화
],
};
플러그인을 사용한 개발 서버 설정
Rollup은 기본적으로 개발 서버를 제공하지 않지만, rollup-plugin-serve
와 rollup-plugin-livereload
플러그인을 사용하면 개발 서버와 라이브 리로드 기능을 설정할 수 있습니다.
// rollup.config.js
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import serve from 'rollup-plugin-serve'; // 개발 서버 플러그인
import livereload from 'rollup-plugin-livereload'; // 라이브 리로드 플러그인
export default {
input: 'src/index.js',
output: {
file: 'dist/bundle.js',
format: 'esm',
},
plugins: [
resolve(),
commonjs(),
serve({
open: true, // 브라우저에서 자동으로 열기
contentBase: 'dist', // 서버의 루트 경로
port: 3000, // 개발 서버 포트
}),
livereload('dist'), // dist 폴더를 모니터링하여 변경 시 리로딩
],
};
Esbuild
Esbuild는 Go 언어로 작성된 번들러로, 매우 빠른 속도를 자랑합니다. 특히 코드 파싱, 출력, 소스맵 생성까지 병렬로 처리하여 빠른 빌드를 지원합니다.
그러나 Esbuild는 빌드 도구로서만 작동하며, HMR(Hot Module Replacement)
이나 PostCSS
같은 기능은 기본적으로 제공되지 않으므로 다른 도구와 결합하여 사용해야 합니다.
Esbuild의 주요 특징
- 매우 빠른 번들링 속도: Esbuild는 Go 언어로 작성되어 기존 JavaScript로 작성된 번들러보다 훨씬 빠른 성능을 자랑합니다. 이는 코드 파싱, 출력, 소스맵 생성이 모두 병렬로 처리되기 때문입니다. 대규모 프로젝트에서도 빠르게 번들링할 수 있지만, 그 외의 기능적인 면에서는 제한이 있습니다.
- 다양한 모듈 및 문법 지원: Esbuild는 CommonJS, ES6 모듈, JSX, TypeScript 등을 지원하며, 트리셰이킹을 통해 사용되지 않는 코드를 제거할 수 있습니다. 그러나 ES5 이하의 문법을 완벽하게 지원하지 않기 때문에 구형 브라우저(특히 IE)를 지원해야 하는 프로젝트에서는 Esbuild 단독으로 사용하기 어려울 수 있습니다.
- 통합 빌드 도구가 아님: Esbuild는 빌드 도구로서 역할만 제공하기 때문에 통합적인 개발 환경 도구로 사용하려면 다른 툴과 결합해야 합니다. 예를 들어, Vite 또는 Snowpack과 함께 사용하면 Esbuild의 빠른 빌드 속도에 더해 HMR 및 추가적인 기능을 활용할 수 있습니다.
- HMR 및 라이브 리로딩 미지원: Esbuild는 기본적으로 HMR(Hot Module Replacement)나 라이브 리로딩을 지원하지 않습니다. 즉, 개발 환경에서 코드 변경 사항을 실시간으로 반영하는 기능을 사용하려면 다른 툴과 결합하거나 추가 설정이 필요합니다.
- PostCSS 및 기타 전처리기 미지원: Esbuild는 기본적으로 PostCSS나 기타 전처리기를 자동으로 처리하지 않습니다. 이를 사용하려면 플러그인을 추가하거나 Esbuild와 다른 도구를 결합해야 합니다.
- 대규모 프로덕션 사이트에는 적합하지 않음: Esbuild는 아직 버전 1.0 이하로, 대규모 프로덕션 사이트에서는 안정성이 완전히 검증되지 않았습니다. 따라서 대규모 사이트나 복잡한 애플리케이션을 처리할 때는 Webpack이나 Parcel 같은 더 안정적인 번들러를 사용하는 것이 좋습니다.
예시 코드
Esbuild는 CLI(Command Line Interface)를 통해 매우 간단하게 사용할 수 있습니다. 아래는 Esbuild를 사용해 기본적인 자바스크립트 파일을 번들링하고 최소화하는 예시 코드입니다.
# 단순한 자바스크립트 파일 번들링
esbuild src/index.js --bundle --outfile=dist/bundle.js --minify --sourcemap
위 명령어는 src/index.js
파일을 번들링하여 dist/bundle.js
로 출력하고, 소스맵을 생성하며, 파일을 최소화합니다. Esbuild는 이처럼 매우 빠르게 번들링을 처리할 수 있으며, 추가적인 설정 없이도 기본적인 작업을 쉽게 수행할 수 있습니다.
TypeScript 지원 예시
Esbuild는 ES6 모듈 및 JSX를 기본적으로 지원합니다. JSX 파일을 번들링하고 소스맵을 생성하는 방법은 다음과 같습니다.
# JSX 파일 번들링
esbuild src/app.jsx --bundle --outfile=dist/bundle.js --minify --sourcemap
위 명령어를 통해 JSX 파일을 번들링하고, 최소화된 결과물과 함께 소스맵을 생성할 수 있습니다.
ES6 모듈 및 JSX 지원
Esbuild는 ES6 모듈 및 JSX를 기본적으로 지원합니다. JSX 파일을 번들링하고 소스맵을 생성하는 방법은 다음과 같습니다.
# JSX 파일 번들링
esbuild src/app.jsx --bundle --outfile=dist/bundle.js --minify --sourcemap
위 명령어를 통해 JSX 파일을 번들링하고, 최소화된 결과물과 함께 소스맵을 생성할 수 있습니다.
Vite와 결합한 Esbuild 사용 예시
Esbuild는 Vite와 결합하여 사용할 때 가장 큰 장점을 발휘합니다. Vite는 Esbuild를 사용해 개발 환경에서 매우 빠른 HMR을 제공하며, 프로덕션 환경에서는 Rollup을 사용해 번들링 작업을 처리합니다.
Vite와 결합하여 사용하는 기본 설정 예시는 다음과 같습니다.
// package.json
{
"scripts": {
"dev": "vite", // Vite를 사용해 개발 서버 실행
"build": "vite build" // 프로덕션 빌드
},
"devDependencies": {
"vite": "^3.0.0"
}
}
이렇게 Vite와 함께 Esbuild를 사용하면 개발 환경에서 빠른 빌드 속도와 HMR을 동시에 누릴 수 있습니다. Esbuild 단독으로는 제공되지 않는 기능을 Vite와 같은 도구가 보완해줍니다.
Vite
Vite는 현대적인 프레임워크(React, Vue, Preact 등)를 위한 매우 빠르고 간편한 번들러입니다. Esbuild를 사용하여 빠른 빌드 속도를 제공하며, 특히 개발 환경에서 Native ESM을 사용해 번들링 없이 파일을 제공하는 특징이 있습니다. 또한, 프로덕션 환경에서는 Rollup을 사용하여 최적화된 번들링을 지원합니다. 아래는 Vite의 주요 특징과 예시 코드입니다.
Vite의 주요 특징
1. React, Vue, Preact 지원: Vite는 React, Vue, Preact 같은 현대적인 프레임워크와 잘 호환되며, 기존의 CRA(Create React App)나 Vue CLI의 대체재로 자주 사용됩니다. 복잡한 설정 없이 간단하게 시작할 수 있으며, 빠른 개발 속도를 제공합니다.
2. 빠른 사전 번들링 (Pre-bundling): Vite는 개발 시 Esbuild를 사용하여 기존 번들러보다 10배에서 100배 더 빠르게 동작합니다. 이를 통해 종속성(dependencies)을 빠르게 처리하고, 개발 중 빠른 피드백을 제공합니다. Esbuild 덕분에 Vite는 모듈 크기에 관계없이 고속으로 빌드를 수행할 수 있습니다.
3. Native ESM 제공 (개발 환경): Vite는 개발 환경에서 Native ESM(ECMAScript Modules)을 사용하여, 브라우저에서 번들링 없이 온디맨드로 파일을 제공합니다. 이는 컴파일링이 필요한 JSX, CSS, Vue/Svelte 컴포넌트와 같은 소스 코드에 특히 유용합니다. 브라우저가 직접 번들러처럼 동작하기 때문에 필요한 모듈만 가져와 빠르게 로딩할 수 있습니다.
4. Rollup을 사용한 프로덕션 번들링: 프로덕션 환경에서는 Rollup을 사용하여 번들링을 수행합니다. Esbuild가 개발 환경에서 뛰어난 성능을 제공하는 반면, 프로덕션에서는 코드 분할(Code-splitting)과 같은 최적화 기능이 부족하므로, Rollup을 사용해 트리셰이킹, 지연 로딩, 청크 파일 분할 등의 작업을 처리합니다. 이를 통해 프로덕션 환경에서도 최적의 로딩 성능을 얻을 수 있습니다.
5. 빠른 HMR(Hot Module Replacement): Vite는 Native ESM을 사용하기 때문에 빠른 HMR을 기본적으로 지원합니다. 모듈이 수정되면 필요한 부분만 교체되며, 브라우저가 해당 모듈을 요청할 때까지 해당 부분을 번들링하지 않아 효율적입니다. 특히 개발자 경험이 크게 향상됩니다.
6. 패키지와 소스코드 분리 빌드: Vite는 패키지(Dependencies)와 소스코드를 분리하여 빌드합니다. 패키지는 설치된 후에 내용이 바뀌지 않으므로 캐시된 상태로 유지되고, 소스코드는 빈번하게 변경될 수 있기 때문에 이를 효율적으로 분리하여 빠르게 빌드합니다.
7. TypeScript, JSX, CSS 등 기본 지원: Vite는 TypeScript, JSX, CSS를 기본적으로 지원하며, 내부적으로 Esbuild를 사용하여 매우 빠르게 트랜스파일링합니다. 덕분에 추가적인 설정 없이도 다양한 언어와 스타일을 처리할 수 있습니다.
8. 빌드 최적화: Vite는 빌드 시 CSS를 자동으로 추출해 별도의 파일로 분리하고, Direct import 구문에 대해 <link ref="modulepreload">
를 사용하여 모듈을 캐싱하도록 자동으로 변환합니다. 이를 통해 불필요한 네트워크 요청을 줄이고, 빌드된 결과물을 최적화할 수 있습니다.
9. Rollup 설정 복잡성: Vite는 Rollup을 사용한 pre-configured 빌드 환경을 제공하지만, Rollup 설정을 변경하거나 확장하는 것은 다소 복잡할 수 있습니다. Rollup의 설정을 세밀하게 조정하는 경우, 이를 완전히 뜯어내고 수정하는 데 시간이 걸릴 수 있습니다.