PageSourceSearch

https://webpack.kr/5918.adb7a1241e6e5632.js

js webpack.kr collected 2026-09-25 23:38:00 UTC 35,699 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[5918],{5918:function(n,e,s){s.r(e),s.d(e,{default:function(){return i}});var a=s(2540),c=s(9710);function l(n){const e={a:"a",aside:"aside",code:"code",h2:"h2",p:"p",pre:"pre",span:"span",strong:"strong",...(0,c.R)(),...n.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(e.aside,{className:"tip",children:[(0,a.jsx)(e.p,{className:"tip__prefix",children:"tip"}),(0,a.jsxs)(e.p,{children:["이 가이드는 ",(0,a.jsx)(e.a,{href:"/guides/asset-management",children:(0,a.jsx)(e.code,{children:"Asset Management"})})," 가이드에 있는 코드 예제를 기준으로 합니다."]})]}),"\n",(0,a.jsxs)(e.p,{children:["지금까지 모든 애셋을 ",(0,a.jsx)(e.code,{children:"index.html"})," 파일에 수동으로 포함했습니다. 하지만 애플리케이션이 커지면서 ",(0,a.jsx)(e.a,{href:"/guides/caching",children:"파일 이름에 해시를 사용"}),"하거나 ",(0,a.jsx)(e.a,{href:"/guides/code-splitting",children:"다중 번들"}),"로 내보내기 시작하면 ",(0,a.jsx)(e.code,{children:"index.html"})," 파일을 수동으로 관리하기 어렵습니다. 이 때 몇 가지 플러그인으로 이 프로세스를 훨씬 쉽게 관리할 수 있습니다."]}),"\n",(0,a.jsxs)(e.h2,{children:[(0,a.jsx)(e.span,{id:"preparation"}),"Preparation",(0,a.jsx)(e.a,{href:"#preparation","aria-hidden":"true",tabIndex:"-1",children:(0,a.jsx)(e.span,{className:"header-link"})})]}),"\n",(0,a.jsx)(e.p,{children:"먼저 프로젝트를 조금 수정해보겠습니다."}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"project"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-diff",children:[(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" webpack-demo\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" ├── package.json\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" ├── package-lock.json\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" ├── webpack.config.js\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" ├── /dist\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" ├── /src\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" │   ├── index.js\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:" │   ├── print.js\n"})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:" └── /node_modules"})]})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.code,{children:"src/print.js"})," 파일에 로직을 추가합니다."]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"src/print.js"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-js",children:[(0,a.jsx)(e.span,{className:"token keyword",children:"export"})," ",(0,a.jsx)(e.span,{className:"token keyword",children:"default"})," ",(0,a.jsx)(e.span,{className:"token keyword",children:"function"})," ",(0,a.jsx)(e.span,{className:"token function",children:"printMe"}),(0,a.jsx)(e.span,{className:"token punctuation",children:"("}),(0,a.jsx)(e.span,{className:"token punctuation",children:")"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"{"}),"\n  console",(0,a.jsx)(e.span,{className:"token punctuation",children:"."}),(0,a.jsx)(e.span,{className:"token function",children:"log"}),(0,a.jsx)(e.span,{className:"token punctuation",children:"("}),(0,a.jsx)(e.span,{className:"token string",children:'"I get called from print.js!"'}),(0,a.jsx)(e.span,{className:"token punctuation",children:")"}),(0,a.jsx)(e.span,{className:"token punctuation",children:";"}),"\n",(0,a.jsx)(e.span,{className:"token punctuation",children:"}"})]})}),"\n",(0,a.jsxs)(e.p,{children:["그리고 ",(0,a.jsx)(e.code,{children:"src/index.js"})," 파일에서 이 함수를 사용합니다."]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"src/index.js"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-diff",children:[(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import _ from 'lodash';
1\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"import printMe from './print.js';\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"function component() {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  const element = document.createElement('div');\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  const btn = document.createElement('button');\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  element.innerHTML = _.join(['Hello', 'webpack'], ' ');\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  btn.innerHTML = 'Click me and check the console!';\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  btn.onclick = printMe;\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  element.appendChild(btn);\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"\n"})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  return element;\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"}\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"document.body.appendChild(component());"})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["webpack이 엔트리를 분할할 수 있도록 ",(0,a.jsx)(e.code,{children:"dist/index.html"})," 파일도 업데이트해 보겠습니다."]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"dist/index.html"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-diff",children:[(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"<!DOCTYPE html>\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"<html>\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  <head>\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:'    <meta charset="utf-8" />\n'})]}),(0,a.jsxs)(e.span,{className:"token deleted-sign deleted",children:[(0,a.jsx)(e.span,{className:"token prefix deleted",children:"-"}),(0,a.jsx)(e.span,{className:"token line",children:"    <title>Asset Management</title>\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    <title>Output Management</title>\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:'    <script src="./print.bundle.js"><\/script>\n'})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  </head>\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  <body>\n"})]}),(0,a.jsxs)(e.span,{className:"token deleted-sign deleted",children:[(0,a.jsx)(e.span,{className:"token prefix deleted",children:"-"}),(0,a.jsx)(e.span,{className:"token line",children:'    <script src="bundle.js"><\/script>\n'})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:'    <script src="./index.bundle.js"><\/script>\n'})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  </body>\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"</html>"})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["이제 설정을 수정합니다. ",(0,a.jsx)(e.code,{children:"src/print.js"}),"를 새 엔트리 포인트(",(0,a.jsx)(e.code,{children:"print"}),")로 추가합니다. 그리고 출력 번들 이름이 엔트리 포인트 이름을 기반으로 동적으로 생성되도록 변경합니다."]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"webpack.config.js"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-diff",children:[(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import path from 'node:path';\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import { fileURLToPath } from 'node:url';\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"const __filename = fileURLToPath(import.meta.url);\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"const __dirname = path.dirname(__filename);\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"export default {\n"})]}),(0,a.jsxs)(e.span,{className:"token deleted-sign deleted",children:[(0,a.jsx)(e.span,{className:"token prefix deleted",children:"-"}),(0,a.jsx)(e.span,{className:"token line",children:"  entry: './src/index.js',\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  entry: {\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    index: './src/index.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    print: './src/print.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  },\n"})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  output: {\n"})]}),(0,a.jsxs)(e.span,{className:"token deleted-sign deleted",children:[(0,a.jsx)(e.span,{className:"token prefix deleted",children:"-"}),(0,a.jsx)(e.span,{className:"token line",children:"    filename: 'bundle.js',\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    filename: '[name].bundle.js',\n"})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    path: path.resolve(__dirname, 'dist'),\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  },\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"};"})]})]})}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.code,{children:"npm run build"}),"를 실행하고 무엇이 생성되는지 살펴보겠습니다."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-bash",children:[(0,a.jsx)(e.span,{className:"token punctuation",children:".."}),".\n",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"webpack-cli",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," Compilation finished\nasset index.bundle.js ",(0,a.jsx)(e.span,{className:"token number",children:"69.5"})," KiB ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"emitted",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"minimized",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"("}),"name: index",(0,a.jsx)(e.span,{className:"token punctuation",children:")"})," ",(0,a.jsx)(e.span,{className:"token number",children:"1"})," related asset\nasset print.bundle.js ",(0,a.jsx)(e.span,{className:"token number",children:"316"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"emitted",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"minimized",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"("}),"name: print",(0,a.jsx)(e.span,{className:"token punctuation",children:")"}),"\nruntime modules ",(0,a.jsx)(e.span,{className:"token number",children:"1.36"})," KiB ",(0,a.jsx)(e.span,{className:"token number",children:"7"})," modules\ncacheable modules ",(0,a.jsx)(e.span,{className:"token number",children:"530"})," KiB\n  ./src/index.js ",(0,a.jsx)(e.span,{className:"token number",children:"406"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"built",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"code generated",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\n  ./src/print.js ",(0,a.jsx)(e.span,{className:"token number",children:"83"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"built",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"code generated",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\n  ./node_modules/lodash/lodash.js ",(0,a.jsx)(e.span,{className:"token number",children:"530"})," KiB ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"built",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"code generated",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\nwebpack ",(0,a.jsx)(e.span,{className:"token number",children:"5"}),".x.x compiled successfully ",(0,a.jsx)(e.span,{className:"token keyword",children:"in"})," ",(0,a.jsx)(e.span,{className:"token number",children:"1996"})," ms"]})}),"\n",(0,a.jsxs)(e.p,{children:["webpack이 ",(0,a.jsx)(e.code,{children:"print.bundle.js"})," 과 ",(0,a.jsx)(e.code,{children:"index.bundle.js"}
1)," 파일을 생성하는 것을 볼 수 있습니다. 이 파일은 ",(0,a.jsx)(e.code,{children:"index.html"})," 파일에도 명시되어 있습니다. 브라우저에서 ",(0,a.jsx)(e.code,{children:"index.html"}),"을 열고 버튼을 클릭하면 어떻게 되는지 확인할 수 있습니다."]}),"\n",(0,a.jsxs)(e.p,{children:["그러나 엔트리 포인트 중 하나의 이름을 변경하거나 새 엔트리 포인트를 추가하면 어떻게 될까요? 생성된 번들은 빌드에서 이름이 변경되지만 ",(0,a.jsx)(e.code,{children:"index.html"})," 파일은 여전히 예전 이름을 참조합니다. ",(0,a.jsx)(e.a,{href:"/plugins/html-webpack-plugin",children:(0,a.jsx)(e.code,{children:"HtmlWebpackPlugin"})}),"을 사용하여 이 문제를 해결해보겠습니다."]}),"\n",(0,a.jsxs)(e.aside,{className:"tip",children:[(0,a.jsx)(e.p,{className:"tip__prefix",children:"tip"}),(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.code,{children:"print.bundle.js"})," 파일을 검사해 보면 ",(0,a.jsx)(e.code,{children:"printMe"})," 함수가 없는 것을 알 수 있습니다. 대신, 눈에 띄는 부작용이 없는 즉시 실행 함수 표현식(IIFE)만 포함되어 있습니다.",(0,a.jsx)("br",{}),(0,a.jsx)("br",{}),"\n이는 현재 설정에서 webpack이 각 진입점을 번들이 로드될 때 실행되는 독립 실행형 프로그램으로 취급하기 때문입니다. ",(0,a.jsx)(e.code,{children:"print.js"}),"는 함수만 내보내고 ",(0,a.jsx)(e.code,{children:"printMe()"}),"를 호출하지 않으므로, 자체 진입점으로 실행하는 데 실행 가능한 런타임 코드가 필요하지 않습니다. 따라서 눈에 띄는 부작용이 없으므로 해당 코드를 최적화로 생략할 수 있습니다.",(0,a.jsx)("br",{}),(0,a.jsx)("br",{}),"\n반면, ",(0,a.jsx)(e.code,{children:"index.js"}),"는 ",(0,a.jsx)(e.code,{children:"printMe"}),"를 가져와 사용하므로 webpack은 ",(0,a.jsx)(e.code,{children:"index.bundle.js"}),"에 해당 함수를 직접 포함합니다. Webpack은 모듈 번들러이므로 ",(0,a.jsx)(e.code,{children:"index.bundle.js"})," 파일에는 해결되지 않은 import 문 대신 실행에 필요한 모든 코드가 포함되어 있다는 점을 기억하세요.",(0,a.jsx)("br",{}),(0,a.jsx)("br",{}),"\n여기서는 출력 관리 및 ",(0,a.jsx)(e.code,{children:"HtmlWebpackPlugin"}),"을 시연하기 위해 여러 진입점을 사용했습니다. 실제 프로젝트에서는 일반적으로 이와 같은 유틸리티 모듈에 대해 별도의 진입점을 만들지 않습니다. 종속성을 공유하는 여러 진입점이 있는 경우 코드 분할 가이드의 ",(0,a.jsx)(e.a,{href:"/guides/code-splitting/#prevent-duplication",children:"중복 방지"}),"를 참고하세요."]})]}),"\n",(0,a.jsxs)(e.h2,{children:[(0,a.jsx)(e.span,{id:"setting-up-htmlwebpackplugin"}),"Setting up HtmlWebpackPlugin",(0,a.jsx)(e.a,{href:"#setting-up-htmlwebpackplugin","aria-hidden":"true",tabIndex:"-1",children:(0,a.jsx)(e.span,{className:"header-link"})})]}),"\n",(0,a.jsxs)(e.p,{children:["먼저 플러그인을 설치하고 ",(0,a.jsx)(e.code,{children:"webpack.config.js"})," 파일을 수정합니다."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-bash",children:[(0,a.jsx)(e.span,{className:"token function",children:"npm"})," ",(0,a.jsx)(e.span,{className:"token function",children:"install"})," --save-dev html-webpack-plugin"]})}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"webpack.config.js"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-diff",children:[(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import path from 'node:path';\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import { fileURLToPath } from 'node:url';\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"import HtmlWebpackPlugin from 'html-webpack-plugin';\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"const __filename = fileURLToPath(import.meta.url);\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"const __dirname = path.dirname(__filename);\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"export default {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  entry: {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    index: './src/index.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    print: './src/print.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  },\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  plugins: [\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    new HtmlWebpackPlugin({\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"      title: 'Output Management',\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    }),\n"}),(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"  ],\n"})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  output: {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    filename: '[name].bundle.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    path: path.resolve(__dirname, 'dist'),\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  },\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"};"})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["빌드하기 전에 ",(0,a.jsx)(e.code,{children:"dist/"})," 폴더에 이미 ",(0,a.jsx)(e.code,{children:"index.html"}),"이 있더라도 기본적으로 ",(0,a.jsx)(e.code,{children:"HtmlWebpackPlugin"}),"이 자체 ",(0,a.jsx)(e.code,{children:"index.html"}
1)," 파일을 생성하는 것을 알아두세요. 이는 ",(0,a.jsx)(e.code,{children:"index.html"})," 파일이 새로 생성된 파일로 대체된다는 의미입니다. ",(0,a.jsx)(e.code,{children:"npm run build"}),"를 실행할 때 어떤 일이 발생하는지 살펴보겠습니다."]}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-bash",children:[(0,a.jsx)(e.span,{className:"token punctuation",children:".."}),".\n",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"webpack-cli",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," Compilation finished\nasset index.bundle.js ",(0,a.jsx)(e.span,{className:"token number",children:"69.5"})," KiB ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"compared ",(0,a.jsx)(e.span,{className:"token keyword",children:"for"})," emit",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"minimized",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"("}),"name: index",(0,a.jsx)(e.span,{className:"token punctuation",children:")"})," ",(0,a.jsx)(e.span,{className:"token number",children:"1"})," related asset\nasset print.bundle.js ",(0,a.jsx)(e.span,{className:"token number",children:"316"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"compared ",(0,a.jsx)(e.span,{className:"token keyword",children:"for"})," emit",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"minimized",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"("}),"name: print",(0,a.jsx)(e.span,{className:"token punctuation",children:")"}),"\nasset index.html ",(0,a.jsx)(e.span,{className:"token number",children:"253"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"emitted",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\nruntime modules ",(0,a.jsx)(e.span,{className:"token number",children:"1.36"})," KiB ",(0,a.jsx)(e.span,{className:"token number",children:"7"})," modules\ncacheable modules ",(0,a.jsx)(e.span,{className:"token number",children:"530"})," KiB\n  ./src/index.js ",(0,a.jsx)(e.span,{className:"token number",children:"406"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"built",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"code generated",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\n  ./src/print.js ",(0,a.jsx)(e.span,{className:"token number",children:"83"})," bytes ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"built",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"code generated",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\n  ./node_modules/lodash/lodash.js ",(0,a.jsx)(e.span,{className:"token number",children:"530"})," KiB ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"built",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"})," ",(0,a.jsx)(e.span,{className:"token punctuation",children:"["}),"code generated",(0,a.jsx)(e.span,{className:"token punctuation",children:"]"}),"\nwebpack ",(0,a.jsx)(e.span,{className:"token number",children:"5"}),".x.x compiled successfully ",(0,a.jsx)(e.span,{className:"token keyword",children:"in"})," ",(0,a.jsx)(e.span,{className:"token number",children:"2189"})," ms"]})}),"\n",(0,a.jsxs)(e.p,{children:["코드 편집기에서 ",(0,a.jsx)(e.code,{children:"index.html"}),"을 열면 ",(0,a.jsx)(e.code,{children:"HtmlWebpackPlugin"}),"이 완전히 새로운 파일을 생성했으며 모든 번들이 자동으로 추가된 것을 알 수 있습니다."]}),"\n",(0,a.jsxs)(e.p,{children:[(0,a.jsx)(e.code,{children:"HtmlWebpackPlugin"}),"이 제공하는 모든 기능과 옵션에 대해 더 자세히 알아보려면 ",(0,a.jsx)(e.a,{href:"https://github.com/jantimon/html-webpack-plugin",children:(0,a.jsx)(e.code,{children:"HtmlWebpackPlugin"})})," 저장소를 확인해 보세요."]}),"\n",(0,a.jsxs)(e.h2,{children:[(0,a.jsx)(e.span,{id:"cleaning-up-the-dist-folder"}),"Cleaning up the ",(0,a.jsx)(e.code,{children:"/dist"})," folder",(0,a.jsx)(e.a,{href:"#cleaning-up-the-dist-folder","aria-hidden":"true",tabIndex:"-1",children:(0,a.jsx)(e.span,{className:"header-link"})})]}),"\n",(0,a.jsxs)(e.p,{children:["이전 가이드와 코드 예제에서 눈치챘겠지만 ",(0,a.jsx)(e.code,{children:"/dist"})," 폴더가 상당히 복잡해졌습니다. webpack은 파일ì
1„ 생성하여 ",(0,a.jsx)(e.code,{children:"/dist"})," 폴더에 저장하지만, 프로젝트에서 실제로 사용하는 파일이 어떤 건지는 알지 못합니다."]}),"\n",(0,a.jsxs)(e.p,{children:["일반적으로 사용하는 파일만 생성되도록 각 빌드 전에 ",(0,a.jsx)(e.code,{children:"/dist"})," 폴더를 정리하는 것이 좋습니다. ",(0,a.jsx)(e.a,{href:"/configuration/output/#outputclean",children:(0,a.jsx)(e.code,{children:"output.clean"})})," 옵션을 사용하여 처리해보겠습니다."]}),"\n",(0,a.jsx)(e.p,{children:(0,a.jsx)(e.strong,{children:"webpack.config.js"})}),"\n",(0,a.jsx)(e.pre,{children:(0,a.jsxs)(e.code,{className:"hljs language-diff",children:[(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import path from 'node:path';\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import { fileURLToPath } from 'node:url';\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"import HtmlWebpackPlugin from 'html-webpack-plugin';\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"const __filename = fileURLToPath(import.meta.url);\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"const __dirname = path.dirname(__filename);\n"})]}),"\n",(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"export default {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  entry: {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    index: './src/index.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    print: './src/print.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  },\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  plugins: [\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    new HtmlWebpackPlugin({\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"      title: 'Output Management',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    }),\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  ],\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  output: {\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    filename: '[name].bundle.js',\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"    path: path.resolve(__dirname, 'dist'),\n"})]}),(0,a.jsxs)(e.span,{className:"token inserted-sign inserted",children:[(0,a.jsx)(e.span,{className:"token prefix inserted",children:"+"}),(0,a.jsx)(e.span,{className:"token line",children:"    clean: true,\n"})]}),(0,a.jsxs)(e.span,{className:"token unchanged",children:[(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"  },\n"}),(0,a.jsx)(e.span,{className:"token prefix unchanged",children:" "}),(0,a.jsx)(e.span,{className:"token line",children:"};"})]})]})}),"\n",(0,a.jsxs)(e.p,{children:["이제 ",(0,a.jsx)(e.code,{children:"npm run build"}),"를 실행하고 ",(0,a.jsx)(e.code,{children:"/dist"})," 폴더를 확인해보세요. 모든 것이 잘 되었다면 이제 오래된 파일 없이 빌드에서 생성된 파일만 ë³¼ 수 있습니다!"]}),"\n",(0,a.jsxs)(e.h2,{children:[(0,a.jsx)(e.span,{id:"the-manifest"}),"The Manifest",(0,a.jsx)(e.a,{href:"#the-manifest","aria-hidden":"true",tabIndex:"-1",children:(0,a.jsx)(e.span,{className:"header-link"})})]}),"\n",(0,a.jsxs)(e.p,{children:['webpackê³¼ 플러그인은 어떤 파일이 생성되는 것을 어떻게 "알고 있는지" 궁금할 것입니다. 답은 매니페스트에 있습니다. webpack은 모든 모듈이 출력 번들에 어떻게 매핑되는지 추적합니다. 만약 webpack의 ',(0,a.jsx)(e.a,{href:"/configuration/output",children:(0,a.jsx)(e.code,{children:"output"})}),"을 다른 방식으로 관리하는데 관심이 있다면 매니페스트부터 시작하는 것이 좋습니다."]}
1),"\n",(0,a.jsxs)(e.p,{children:["매니페스트 데이터는 ",(0,a.jsx)(e.a,{href:"/plugins/manifest-plugin/",children:(0,a.jsx)(e.code,{children:"ManifestPlugin"})}),"을 사용하여 쉽게 적용 가능한 json 파일로 추출할 수 있습니다."]}),"\n",(0,a.jsxs)(e.p,{children:["프로젝트에서 이 플러그인을 사용하는 방법에 대한 모든 예제를 다루지는 않겠지만 ",(0,a.jsx)(e.a,{href:"/concepts/manifest",children:"콘셉 페이지"})," 및 ",(0,a.jsx)(e.a,{href:"/guides/caching",children:"캐싱 가이드"}),"를 읽어 보면 이것이 장기 캐싱과 어떻게 연결되는지 확인할 수 있습니다."]}),"\n",(0,a.jsxs)(e.h2,{children:[(0,a.jsx)(e.span,{id:"conclusion"}),"Conclusion",(0,a.jsx)(e.a,{href:"#conclusion","aria-hidden":"true",tabIndex:"-1",children:(0,a.jsx)(e.span,{className:"header-link"})})]}),"\n",(0,a.jsxs)(e.p,{children:["HTML에 번들을 동적으로 추가하는 방법을 배웠으므로 이제 ",(0,a.jsx)(e.a,{href:"/guides/development",children:"개발 가이드"}),"를 살펴보세요. 또는 심화 항목을 자세히 알아보고 싶다면 ",(0,a.jsx)(e.a,{href:"/guides/code-splitting",children:"코드 스플리팅 가이드"}),"를 추천합니다."]})]})}function i(n={}){const{wrapper:e}={...(0,c.R)(),...n.components};return e?(0,a.jsx)(e,{...n,children:(0,a.jsx)(l,{...n})}):l(n)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.