본문 바로가기

Webpack 기초

entry·output·loader·plugin의 역할을 이해하고 JavaScript·CSS·이미지 의존성을 브라우저용 번들로 빌드합니다.

현대 웹 개발, 특히 React 같은 SPA(Single Page Application)에서는 수많은 JavaScript 모듈, CSS, 이미지 에셋을 사용합니다.

이 파일들은 개발 단계에서는 분리되어 있지만, 브라우저 실행 단계에서는 다음 문제와 마주칩니다.

  • HTTP 요청 수 증가: 수백 개의 파일을 각각 요청하면 네트워크 지연이 발생하고 성능이 저하됩니다.
  • 모듈 의존성 관리 복잡성: 각 모듈이 다른 모듈에 의존하는 경우, 로딩 순서 등을 수동으로 관리하기 어렵습니다.
  • 브라우저 호환성 문제: 최신 JavaScript(ES6+) 문법이나 TypeScript, Sass 등의 CSS 전처리기 등은 모든 브라우저에서 직접 지원되지 않습니다.
  • 배포 최적화 어려움: 코드 압축, 이미지 최적화 등의 배포 전 최적화 작업을 수동으로 하기는 비효율적입니다.

이러한 문제들을 해결하고, 복잡한 웹 프로젝트의 효율적인 개발 및 배포를 돕기 위해 등장한 것이 바로 모듈 번들러(Module Bundler)입니다.

Webpack은 모듈 그래프와 loader·plugin을 직접 설정할 수 있는 번들러입니다. 여기서는 도구의 사용 비율보다 실제 설정이 어떤 입력을 어떤 산출물로 바꾸는지 확인합니다.

이번 장에서는 Webpack의 기본 개념과 동작 원리, 핵심 설정을 사용해 간단한 프로젝트를 빌드하는 방법을 학습합니다.

Webpack은 모듈을 번들로 묶고, 로더와 플러그인을 통해 JavaScript 외 에셋과 빌드 결과물을 처리합니다.

Webpack 빌드와 브라우저 실행 파이프라인 — 상태 추적

본문 Count 예제의 소스·빌드 산출물·브라우저 상태가 다른 시점에 존재한다. CSS loader 처리/주입과 클릭 상태 변화가 Webpack 전체 재빌드와 다름을 추적할 가치가 있다.

Webpack은 의존성을 빌드하고, 브라우저는 그 산출물을 실행합니다

BUILD → RUNTIME

Webpack은 의존성을 빌드하고, 브라우저는 그 산출물을 실행합니다

이 절의 최종 설정은 src/index.js에서 App과 CSS를 따라가 dist/index.html과 bundle.js를 만듭니다. style-loader 설정에서는 CSS도 JavaScript를 통해 실행 시 주입됩니다.

빌드의책임과브라우저상태갱신을나눈다5노드4진행관계. CSS chain은css-loader뒤style-loader이며최종HTML+bundle을브라우저가실행한다. CSSstyle주입과Count사용자갱신은런타임이고클릭마다Webpack전체빌드가아니다. 실제import이미지/폰트만asset규칙조건이며mobile같다.
소스 import 그래프entry → App·CSS
연결 관계소스 import 그래프 · entry → App·CSS → Node 빌드 · loader + plugin
Node 빌드loader + plugin
연결 관계Node 빌드 · loader + plugin → 생성 산출물 · HTML + bundle.js
생성 산출물HTML + bundle.js
연결 관계생성 산출물 · HTML + bundle.js → 브라우저 실행 · CSS 주입·React
브라우저 실행CSS 주입·React
연결 관계브라우저 실행 · CSS 주입·React → 사용자 입력 · Count 상태 갱신
사용자 입력Count 상태 갱신

입력 · 소스 의존성

src/index.js
├─ App.js
└─ styles.css

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에서 의존 파일을 찾는다의존 그래프가 변환 대상 파일을 정한다
변환과 실행산출: 번들 자원 / 브라우저: 초기 UIloader/번들 산출을 브라우저가 읽고 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를 통해 실행 시 주입됩니다.

빌드의책임과브라우저상태갱신을나눈다5노드4진행관계. CSS chain은css-loader뒤style-loader이며최종HTML+bundle을브라우저가실행한다. CSSstyle주입과Count사용자갱신은런타임이고클릭마다Webpack전체빌드가아니다. 실제import이미지/폰트만asset규칙조건이며mobile같다.
소스 import 그래프entry → App·CSS
연결 관계소스 import 그래프 · entry → App·CSS → Node 빌드 · loader + plugin
Node 빌드loader + plugin
연결 관계Node 빌드 · loader + plugin → 생성 산출물 · HTML + bundle.js
생성 산출물HTML + bundle.js
연결 관계생성 산출물 · HTML + bundle.js → 브라우저 실행 · CSS 주입·React
브라우저 실행CSS 주입·React
연결 관계브라우저 실행 · CSS 주입·React → 사용자 입력 · Count 상태 갱신
사용자 입력Count 상태 갱신

입력 · 소스 의존성

src/index.js
├─ App.js
└─ styles.css

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에서 의존 파일을 찾는다의존 그래프가 변환 대상 파일을 정한다
변환과 실행산출: 번들 자원 / 브라우저: 초기 UIloader/번들 산출을 브라우저가 읽고 CSS를 적용한다빌드 단계와 브라우저 실행을 구분한다
Count 클릭앱 state: 증가 / 번들: 같은 파일실행 중 앱의 count가 바뀐다사용자 클릭은 소스 재빌드를 수행하지 않는다

모듈 번들러(Module Bundler)란?

모듈 번들러는 애플리케이션을 구성하는 여러 개의 모듈(JavaScript 파일, CSS 파일, 이미지 등)을 분석하고, 이들의 의존성을 파악하여 최종적으로 브라우저에서 실행 가능한 형태의 하나 또는 여러 개의 파일(번들)로 합쳐주는 도구입니다.

주요 역할
  • 모듈 의존성 해결: import, require() 등으로 연결된 모듈들을 찾아내 하나의 그래프를 만듭니다.
  • 코드 번들링: 수많은 모듈 파일을 웹 브라우저가 효율적으로 로드할 수 있는 몇 개의 파일로 묶습니다.
  • 트랜스파일링(Transpiling): Babel과 같은 도구와 연동하여 ES6+ JavaScript 코드를 구형 브라우저가 이해할 수 있는 ES5 코드로 변환합니다.
  • 에셋 처리: CSS, 이미지, 폰트 파일 등 JavaScript 코드가 아닌 에셋들도 모듈처럼 처리하여 번들에 포함시키거나 최적화합니다.
  • 코드 최적화: 코드 압축(Minification), 난독화(Uglification), 트리 쉐이킹(Tree Shaking) 등을 통해 최종 번들 파일의 크기를 줄입니다.
  • 개발 서버 제공: 개발 중 빠른 피드백을 위해 웹 서버를 제공하고, 설정과 변경 종류에 따라 페이지 새로고침 또는 변경 모듈을 교체하는 HMR(Hot Module Replacement)을 사용합니다.

Vite 같은 개발·빌드 도구와 Parcel, Rollup 등도 있습니다. 도구를 비교할 때는 개발 서버, 번들링, 확장 설정의 역할과 프로젝트 조건을 확인합니다.


Webpack 핵심 개념

Webpack을 이해하려면 몇 가지 핵심 개념을 알아야 합니다.

  • Entry (엔트리)
    • Webpack이 번들링을 시작할 지점, 즉 애플리케이션의 메인 JavaScript 파일입니다.
    • Webpack은 엔트리 파일을 시작으로 모든 의존성 모듈을 재귀적으로 따라가며 하나의 의존성 그래프를 만듭니다.
    • webpack.config.js 파일에서 entry 속성으로 지정합니다.
      module.exports = {
        entry: './src/index.js', // 단일 엔트리
        // entry: { app: './src/app.js', vendor: './src/vendor.js' }, // 다중 엔트리
      };
  • Output (아웃풋)
    • Webpack이 생성한 번들 파일을 저장할 경로와 파일 이름입니다.
    • output 속성으로 지정합니다.
      const path = require('path');
      module.exports = {
        output: {
          filename: 'bundle.js', // 번들 파일 이름
          path: path.resolve(__dirname, 'dist'), // 번들 파일 저장 경로
          clean: true, // 빌드 전 output 디렉토리 정리
        },
      };
  • Loader (로더)
    • Webpack은 JavaScript·JSON을 기본 처리하며, Webpack 5의 Asset Modules로 이미지·폰트도 다룰 수 있습니다. CSS 처리나 JSX 문법 변환에는 아래 예제처럼 loader를 연결합니다.
    • 개발자가 직접 작성하는 것이 아니라, 이미 만들어진 로더(예: css-loader, style-loader, babel-loader, file-loader)를 설정에 추가하여 사용합니다.
    • module.rules 배열 안에 정의합니다.
      module.exports = {
        module: {
          rules: [
            {
              test: /\.css$/, // .css 확장자를 가진 파일에 적용
              use: ['style-loader', 'css-loader'], // 적용할 로더 배열
            },
            {
              test: /\.js$/, // .js 확장자를 가진 파일에 적용
              exclude: /node_modules/, // node_modules 디렉토리 제외
              use: {
                loader: 'babel-loader', // babel-loader 사용 (ES6+ -> ES5)
                options: {
                  presets: ['@babel/preset-env', '@babel/preset-react'],
                },
              },
            },
          ],
        },
      };
  • Plugin (플러그인)
    • 로더가 특정 파일을 변환하는 데 집중한다면, 플러그인은 번들링 과정 전반에 걸쳐 다양한 추가 기능을 수행합니다.
    • 코드 최적화(번들 파일 압축), 에셋 관리(HTML 파일 생성, 이미지 최적화), 환경 변수 주입 등 로더로는 할 수 없는 광범위한 작업을 수행합니다.
    • plugins 배열 안에 정의합니다.
      const HtmlWebpackPlugin = require('html-webpack-plugin');
      const MiniCssExtractPlugin = require('mini-css-extract-plugin');
      module.exports = {
        plugins: [
          new HtmlWebpackPlugin({
            template: './public/index.html', // HTML 템플릿 파일 지정
          }),
          new MiniCssExtractPlugin({
            filename: 'styles/[name].css', // CSS 파일을 별도 파일로 추출
          }),
        ],
      };
  • Mode (모드)

Webpack의 loader 체인과 모드 설정을 현재 설정의 실제 처리 책임과 대조합니다.

  • development, production, none 세 가지 모드를 제공합니다. 각 모드에 따라 Webpack의 내부 최적화 설정이 자동으로 적용됩니다.
  • production 모드: 코드 압축, 트리 쉐이킹 등 배포를 위한 최적화가 기본으로 활성화됩니다.
  • development 모드: 빠른 빌드 속도와 디버깅 편의성을 위해 최적화 기능이 비활성화됩니다.
    module.exports = {
      mode: 'development', // 'production' 또는 'none'으로 설정 가능
    };

Webpack으로 React 앱 빌드하기 (간단 예제)

이제 간단한 React 프로젝트를 Webpack으로 빌드하는 과정을 통해 핵심 개념들을 실습해 보겠습니다.

앞 절의 Node·npm과 package.json 읽기가 선수 지식입니다. 아래 명령의 버전 미지정 패키지는 실행 시점에 따라 달라질 수 있습니다. 이 장의 예제를 Babel 7 환경으로 맞추려면 Babel 관련 세 패키지는 다음처럼 메이저를 정하고 해결된 lock·Node·npm·loader 호환 범위를 함께 기록합니다. 기존 설치 명령은 도구 목록 설명으로 유지하되 두 버전 정책을 섞지 않습니다.

npm install --save-dev @babel/core@7 @babel/preset-env@7 @babel/preset-react@7

위 Babel 7 명령은 아래 my-webpack-app 초기화를 마친 뒤 그 폴더에서 실행합니다. 아래 기존 설치 예시를 사용할 때도 세 Babel 항목을 각각 @7로 지정해 같은 버전 정책을 유지합니다.

작업할 빈 실습 폴더와 public·src 디렉터리를 먼저 준비합니다. snippets의 package.json scripts는 기존 객체에 병합하는 부분입니다. 폴더나 나머지 의존성을 그 짧은 객체로 덮어쓰지 않습니다.

프로젝트 초기화 및 기본 패키지 설치
mkdir my-webpack-app
cd my-webpack-app
npm init -y

# React 및 Webpack 관련 패키지 설치
npm install react react-dom
npm install --save-dev webpack webpack-cli webpack-dev-server html-webpack-plugin style-loader css-loader babel-loader @babel/core @babel/preset-env @babel/preset-react
public/index.html 파일 생성
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My Webpack React App</title>
</head>
<body>
    <div id="root"></div>
</body>
</html>
src/index.js 파일 생성 (엔트리 파일)
src/index.js
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App'; // App 컴포넌트 임포트
import './styles.css'; // CSS 파일 임포트

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
src/App.js 파일 생성 (React 컴포넌트)
src/App.js
// src/App.js
import React, { useState } from 'react';

function App() {
  const [count, setCount] = useState(0);

  return (
    <div className="App">
      <h1>Hello, Webpack & React!</h1>
      <p>Count: {count}</p>
      <button onClick={() => setCount(prev => prev + 1)}>Increment</button>
    </div>
  );
}

export default App;
src/styles.css 파일 생성
src/styles.css
/* src/styles.css */
body {
    font-family: sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
}

.App {
    background-color: white;
    padding: 30px;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    text-align: center;
}

button {
    padding: 10px 20px;
    font-size: 16px;
    cursor: pointer;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 5px;
    transition: background-color 0.3s ease;
}

button:hover {
    background-color: #0056b3;
}
.babelrc 파일 생성 (Babel 설정)
.babelrc
// .babelrc
{
  "presets": [
    "@babel/preset-env",  // 최신 JS 문법을 타겟 환경에 맞춰 변환
    "@babel/preset-react" // JSX 문법을 JS로 변환
  ]
}
webpack.config.js 파일 생성 (Webpack 설정)
webpack.config.js
// webpack.config.js
const 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) 활성화
  },
};
package.json 스크립트 추가

package.json 파일의 scripts 섹션을 다음과 같이 수정합니다.

package.json
{
  "scripts": {
    "start": "webpack serve --mode development",
    "build": "webpack --mode production"
  }
}

기존 package.json의 scripts 객체에 start와 build를 병합합니다.

start는 개발 서버를 실행하고, build는 프로덕션 번들을 생성합니다.

개발 서버 실행 및 빌드
  • 개발 서버 실행
    npm start
    브라우저가 자동으로 열리고 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·런타임 화면을 각각 대조합니다.


Webpack 학습 정리

이번 장에서는 모던 웹 개발의 핵심 도구인 Webpack의 기초를 학습했습니다.

이번 절에서는 모듈 번들러의 필요성과 Webpack의 Entry, Output, Loader, Plugin, Mode 역할을 구분했습니다.

로더는 JavaScript 외 에셋을 처리하고, 플러그인은 번들링 과정의 부가 작업과 최적화를 담당합니다.

또한, 직접 React 프로젝트를 설정하고 webpack.config.js 파일을 작성하여 JavaScript, CSS, 이미지 등을 번들링하고, 개발 서버를 실행하며, 최종 프로덕션 빌드를 수행하는 과정을 실습했습니다.

Webpack은 모듈 번들링, 로더, 플러그인, 빌드 모드의 역할을 이해한 뒤 프로젝트 요구에 맞게 적용해야 합니다.

다음 절에서는 Babel과 Polyfill로 대상 환경의 호환성을 보완하는 방법을 다룹니다.

Webpack 설정은 entry에서 dist까지 이어지는 빌드 파이프라인으로 읽을 때 문제 원인과 최적화 지점을 빠르게 나눌 수 있습니다.

이 장의 Webpack 빌드·실행 파이프라인은 모듈 번들링을 소스 그래프, 변환·최적화, 산출물 배포, 브라우저 로딩 순서로 정리합니다.