entry에서 import 관계를 따라갑니다. 이미지·폰트는 실제 import한 경우 asset/resource 규칙의 처리 대상이 됩니다.
Node에서 수행하는 빌드
JS·JSX: babel-loader가 문법과 JSX를 변환합니다.
CSS: css-loader → style-loader 순서로 처리합니다. 설정 배열은 [style-loader, css-loader]이지만 실행은 오른쪽부터입니다.
HtmlWebpackPlugin은 템플릿으로 HTML을 만듭니다. 플러그인은 빌드 생명주기의 여러 단계에 관여할 수 있습니다.
최종 설정의 주요 산출물
dist/
├─ index.html
└─ bundle.js
이 설정의 JavaScript 파일명은 bundle.js입니다. CSS는 별도 파일로 추출하지 않고 번들에 포함해 실행 시 주입합니다. 추가 산출물은 가져온 자산과 플러그인 설정에 따라 달라집니다.
브라우저 · HTML → bundle.js
생성된 HTML이 번들을 로드합니다. style-loader 코드가 CSS를 style 요소로 넣고, React의 createRoot가 App을 렌더링합니다.
사용자 입력 → 화면 갱신
App의 Count 버튼을 누르면 상태가 바뀌고 React가 화면을 갱신합니다. Webpack 빌드 단계와 브라우저의 상태 갱신은 서로 다른 작업입니다.
이 예의 조건
원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
관계도의 보충 설명
원도표의 전체 관계·조건·설명
구분
내용
구분도표 이름
내용빌드의 책임과 브라우저 상태 갱신을 나눈다
구분전체 관계·조건 설명
내용노드 5개·진행 관계 4개다. CSS chain은 css-loader 뒤 style-loader이며 최종 HTML+bundle을 브라우저가 실행한다. CSS style 주입과 Count 사용자 갱신은 런타임이고 클릭마다 Webpack 전체 빌드를 하는 것은 아니다. 실제 import한 이미지/폰트만 asset 규칙의 처리 대상이며 mobile도 같다.
전체 상태와 변화 근거
장면
현재 관찰값
설명
변화 이유
소스와 import
현재 관찰값입력: JS·CSS import / 화면: 빌드 전
설명entry에서 의존 파일을 찾는다
변화 이유의존 그래프가 변환 대상 파일을 정한다
변환과 실행
현재 관찰값산출: 번들 자원 / 브라우저: 초기 UI
설명loader/번들 산출을 브라우저가 읽고 CSS를 적용한다
변화 이유빌드 단계와 브라우저 실행을 구분한다
Count 클릭
현재 관찰값앱 state: 증가 / 번들: 같은 파일
설명실행 중 앱의 count가 바뀐다
변화 이유사용자 클릭은 소스 재빌드를 수행하지 않는다
Webpack 빌드와 브라우저 실행 파이프라인 — 상태 추적
본문 Count 예제의 소스·빌드 산출물·브라우저 상태가 다른 시점에 존재한다. CSS loader 처리/주입과 클릭 상태 변화가 Webpack 전체 재빌드와 다름을 추적할 가치가 있다.
Webpack은 의존성을 빌드하고, 브라우저는 그 산출물을 실행합니다
BUILD → RUNTIME
Webpack은 의존성을 빌드하고, 브라우저는 그 산출물을 실행합니다
이 절의 최종 설정은 src/index.js에서 App과 CSS를 따라가 dist/index.html과 bundle.js를 만듭니다. style-loader 설정에서는 CSS도 JavaScript를 통해 실행 시 주입됩니다.
entry에서 import 관계를 따라갑니다. 이미지·폰트는 실제 import한 경우 asset/resource 규칙의 처리 대상이 됩니다.
Node에서 수행하는 빌드
JS·JSX: babel-loader가 문법과 JSX를 변환합니다.
CSS: css-loader → style-loader 순서로 처리합니다. 설정 배열은 [style-loader, css-loader]이지만 실행은 오른쪽부터입니다.
HtmlWebpackPlugin은 템플릿으로 HTML을 만듭니다. 플러그인은 빌드 생명주기의 여러 단계에 관여할 수 있습니다.
최종 설정의 주요 산출물
dist/
├─ index.html
└─ bundle.js
이 설정의 JavaScript 파일명은 bundle.js입니다. CSS는 별도 파일로 추출하지 않고 번들에 포함해 실행 시 주입합니다. 추가 산출물은 가져온 자산과 플러그인 설정에 따라 달라집니다.
브라우저 · HTML → bundle.js
생성된 HTML이 번들을 로드합니다. style-loader 코드가 CSS를 style 요소로 넣고, React의 createRoot가 App을 렌더링합니다.
사용자 입력 → 화면 갱신
App의 Count 버튼을 누르면 상태가 바뀌고 React가 화면을 갱신합니다. Webpack 빌드 단계와 브라우저의 상태 갱신은 서로 다른 작업입니다.
이 예의 조건
원도표의 전체 구조와 설명은 위 관계도와 표에서 유지합니다. 아래 인쇄 표에도 원도표의 관계·조건·라벨·설명·주석을 보존합니다.
두 관찰 칸의 위치는 고정입니다. 관찰 상태는 해당 순간의 값이며, 동작·이유는 그 조건에서의 판정과 변화 원인입니다. 독립 비교와 실패 분기는 별도 조건으로 읽고 모든 분기를 한 요청의 필수 실행 순서로 이어 읽지 않습니다.
관계도의 보충 설명
원도표의 전체 관계·조건·설명
구분
내용
구분도표 이름
내용빌드의 책임과 브라우저 상태 갱신을 나눈다
구분전체 관계·조건 설명
내용노드 5개·진행 관계 4개다. CSS chain은 css-loader 뒤 style-loader이며 최종 HTML+bundle을 브라우저가 실행한다. CSS style 주입과 Count 사용자 갱신은 런타임이고 클릭마다 Webpack 전체 빌드를 하는 것은 아니다. 실제 import한 이미지/폰트만 asset 규칙의 처리 대상이며 mobile도 같다.
이제 간단한 React 프로젝트를 Webpack으로 빌드하는 과정을 통해 핵심 개념들을 실습해 보겠습니다.
앞 절의 Node·npm과 package.json 읽기가 선수 지식입니다. 아래 명령의 버전 미지정 패키지는 실행 시점에 따라 달라질 수 있습니다. 이 장의 예제를 Babel 7 환경으로 맞추려면 Babel 관련 세 패키지는 다음처럼 메이저를 정하고 해결된 lock·Node·npm·loader 호환 범위를 함께 기록합니다. 기존 설치 명령은 도구 목록 설명으로 유지하되 두 버전 정책을 섞지 않습니다.
// .babelrc{ "presets": [ "@babel/preset-env", // 최신 JS 문법을 타겟 환경에 맞춰 변환 "@babel/preset-react" // JSX 문법을 JS로 변환 ]}
webpack.config.js 파일 생성 (Webpack 설정)
webpack.config.js
// webpack.config.jsconst path = require('path');const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = { mode: 'development', // 개발 모드 설정 (배포 시 'production'으로 변경) entry: './src/index.js', // 엔트리 포인트 (Webpack이 빌드를 시작할 파일) output: { filename: 'bundle.js', // 빌드된 JavaScript 파일 이름 path: path.resolve(__dirname, 'dist'), // 빌드 결과물이 저장될 디렉토리 경로 (프로젝트 루트의 'dist' 폴더) clean: true, // 빌드 시 이전 빌드 결과물 삭제 }, module: { rules: [ // .css 파일 처리 규칙 { test: /\.css$/, // .css 확장자를 가진 파일에 이 로더들을 적용 use: ['style-loader', 'css-loader'], // style-loader는 CSS를 <style> 태그로 주입, css-loader는 CSS 파일을 JS 모듈로 변환 }, // .js, .jsx 파일 처리 규칙 (Babel을 사용하여 ES6+ 및 JSX 변환) { test: /\.jsx?$/, // .js 또는 .jsx 확장자를 가진 파일에 적용 exclude: /node_modules/, // node_modules 디렉토리는 제외 (성능 향상) use: { loader: 'babel-loader', // Babel 로더 사용 options: { presets: ['@babel/preset-env', '@babel/preset-react'], // .babelrc에 설정된 프리셋 사용 }, }, }, // 이미지 파일 처리 규칙 (Webpack 5부터 기본 제공) { test: /\.(png|svg|jpg|jpeg|gif)$/i, type: 'asset/resource', // 파일을 dist 폴더로 복사하고 URL을 반환 }, // 폰트 파일 처리 규칙 { test: /\.(woff|woff2|eot|ttf|otf)$/i, type: 'asset/resource', }, ], }, plugins: [ new HtmlWebpackPlugin({ template: './public/index.html', // HTML 템플릿 파일 경로 filename: 'index.html', // 빌드될 HTML 파일 이름 }), ], devServer: { static: './dist', // 개발 서버가 정적 파일을 제공할 경로 port: 3000, // 개발 서버 포트 open: true, // 서버 시작 시 브라우저 자동 열기 hot: true, // HMR(Hot Module Replacement) 활성화 },};
브라우저가 자동으로 열리고 React 앱이 http://localhost:3000에서 실행되는 것을 확인할 수 있습니다.
코드를 수정하면 자동으로 새로고침되거나 HMR이 적용됩니다.
프로덕션 빌드
npm run build
dist 디렉터리에 최적화된 index.html과 bundle.js 파일이 생성됩니다.
이 파일들을 웹 서버에 배포하면 됩니다.
Webpack 설정은 파일을 나열하는 일이 아니라, 빌드 목표에 맞춰 변환 책임과 최적화 책임을 나누는 작업입니다.
예시
원 src/index.js가 App과 styles.css를 가져오므로 entry에서 두 의존성을 따라갑니다. CSS loader 배열은 style-loader, css-loader 순서로 적혀 있지만 이 변환 체인은 오른쪽부터 적용합니다. css-loader의 처리 결과를 style-loader가 받아 브라우저 실행 시 style 요소를 넣는 코드를 만듭니다. 최종 plugins에는 HtmlWebpackPlugin만 있으므로 이 설정에서 별도 styles.css 추출을 기대하지 않습니다. 앞의 MiniCssExtractPlugin 목록은 별도 역할 예시이며 실제 추출에는 그 loader 등 전체 설정도 연결해야 합니다.
.babelrc와 최종 options.presets에 같은 프리셋 이름이 보입니다. 둘을 서로 다른 버전·정책으로 바꾸지 말고 다음 절처럼 한 설정 위치로 정리합니다. 이미지·폰트 규칙이 존재한다는 것과 어떤 파일을 실제 import했다는 것도 구별합니다. production 모드의 최적화가 사용자 버튼 클릭 때 다시 빌드되는 것은 아닙니다.
독립 확인
원 App의 Count는 0에서 시작합니다. 버튼을 세 번 눌렀을 때의 값과, 이 상태 갱신에 Webpack 전체 빌드를 세 번 해야 하는지 설명하세요. 설정에 asset/resource 규칙만 있고 실제 이미지 import는 없다면 임의의 이미지 파일이 반드시 dist에 들어가나요? CSS를 별도 파일로 추출하지 않은 현재 최종 설정에서 styles.css 산출물이 없으면 곧바로 실패인가요?
풀이 확인
함수형 갱신이 매번 이전 값에 1을 더하므로 Count는 3입니다. 이미 로드된 React 코드가 상태를 갱신하며 전체 번들 빌드를 클릭마다 다시 하는 것이 아닙니다. 규칙만으로 가져오지 않은 임의 파일까지 처리한다고 기대하지 않습니다. 현재 style-loader 방식은 번들을 통해 CSS를 주입하므로 별도 styles.css가 없는 것만으로 실패라 하지 않습니다. 입력 관계·loader·plugin·런타임 화면을 각각 대조합니다.