Posts WebPack 기초
Post
Cancel

WebPack 기초

Webpack 기본 사용법 (CLI)

React, Vue, Angular중 어느 것을 사용하든 Webpack이라는 녀석을 사용하게 됩니다.

Webpack이란 기본적으로 자바스크립트 모듈 번들러(JavaScript Module Bundler)이며 웹 개발을 도와주는 많은 부가 기능을 가지고 있습니다. 간단한 예제 프로젝트를 통해 Webpack에 대해 알아 보겠습니다.

예제 프로젝트 생성하기

먼저 webpack-example디렉토리를 생성 후 그 안에 예제 프로젝트를 시작 하겠습니다.

1
2
mkdir webpack-example
cd webpack-example

HTML과 Javascript파일 작성

  • index.html
1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Example</title>
  </head>
  <body>
    <script src="./index.js"></script>
  </body>
</html>
  • index.js
1
2
3
4
5
6
7
8
9
10
11
function currentTime() {
  const date = new Date()
  const hours = date.getHours()
  const minutes = date.getMinutes()
  const seconds = date.getSeconds()
  return `${hours}:${minutes}:${seconds}`
}

const div = document.createElement("div")
document.body.appendChild(div)
setInterval(() => (div.innerText = currentTime()), 1000)

외부 라이브러리 사용

Moment.js라는 라이브러리 이용

  • Index.html
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Example</title>
    <script src="https://unpkg.com/moment@2.22.2/moment.js"></script>
  </head>
  <body>
    <script src="./index.js"></script>
  </body>
</html>
  • Index.js
1
2
3
4
5
6
7
function currentTime() {
  return moment().format("H:m:s")
}

const div = document.createElement("div")
document.body.appendChild(div)
setInterval(() => (div.innerText = currentTime()), 1000)

위의 코드는 전통적으로 웹사이트에서 외부 자바스크립트 라이브러리를 사용하던 전형적인 방법입니다. 이러한 방법에는 여러 단점이 존재합니다.

먼저 index.jsindex.html파일 없이는 정상적으로 작동할 수 없습니다.

또한 외부 자바스크립트 라이브러리에 들어있는 모든 변수, 함수, 객체들이 사용 여부에 관계없이 글로벌 네임스페이스를 오염시키게 됩니다. 게다가 외부 라이브러리를 추가적으로 사용할 때 마다 javascript 파일이 아닌 HTML파일을 수정해줘야 된다는 것도 마음에 들지 않습니다.

이는 다른 프로그래밍 언어들처럼 웹에서도 자바스크립트를 통한 자체적인 외부 모듈 임포트 기능이 절실해지는 시점입니다.

NPM으로 외부 라이브러리 설치

좀 더 체계적으로 예제 프로젝트의 외부 라이브러리를 관리하기 위해서 Node.js 패키지 매니저인 NPM을 도입하겠습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
npm init -y
Wrote to /Documents/Project/Web/webpack-example/package.json:

{
  "name": "webpack-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

그리고 Moment.js 패키지를 설치하겠습니다.

1
2
3
4
npm i -S moment
+ moment@2.29.1
added 1 package from 6 contributors and audited 1 package in 0.608s
found 0 vulnerabilities

ES6 Import/Export

ES6는 다른 프로그래밍 언어처럼 하나의 자바스크립트 모듈에서 다른 자바스크립트 모듈을 사용할 수 있도록 importexport와 키워드를 제공합니다.

먼저index.html파일에서 Moment.js의 소스 파일에 대한 CDN링크를 제거합니다. 그리고 index.js파일 맨 위로 Moment.js 패키지를 임포트 합니다.

  • index.js
1
2
3
4
5
6
7
8
9
import moment from "moment"

function currentTime() {
  return moment().format("H:m:s")
}

const div = document.createElement("div")
document.body.appendChild(div)
setInterval(() => (div.innerText = currentTime()), 1000)

index.html파일을 다시 열어보면, 다음과 같이index.js 파일의 import라인에서 구문 에러가 발생한다는 것을 알 수 있습니다.

1
Uncaught SyntaxError: Cannot use import statement outside a module

이를 통해 일반 브라우저는 ES6의 import 키워드를 해석할 수 없다는 것을 알게되었습니다. 이제부터 웹팩(Webpack)를 통해 이 문제를 해결해보도록 하겠습니다.

Webpack과 Webpack CLI 패키지 설치

예제 프로젝트에 webpackwebpack-cli패키지를 설치합니다. Webpack은 웹팩의 핵심 패키지이며 webpack-cli는 터미널에서 webpack커맨드를 실행할 수 있게 해주는 커맨드라인 도구 입니다. 두 개의 패키지 모두 개발할 때만 필요한 의존성이기 때문에 -D 옵션을 사용하였습니다.

1
2
3
4
5
6
7
➜  webpack-example npm i -D webpack
+ webpack@5.33.2
added 73 packages from 121 contributors and audited 74 packages in 10.076s

➜  webpack-example npm i -D webpack-cli
+ webpack-cli@4.6.0
added 50 packages from 40 contributors and audited 124 packages in 4.254s

Webpack Bundle 만들기

프로젝트 디렉토리 안에 소스 디렉토리(src)와 배포 디렉토리(dist)를 생성합니다. 그리고 index.js파일을 소스 디렉토리로 이동시킵니다.

1
2
mkdir src dist
mv index.js src/

그런 다음, 다음과 같이 npx webpack커맨드를 실행시키면, 웹팩이 소스 디렉토리 안의 index.js파일과 그 안에 import 되어 있던 Moment.js 패키지까지 읽어들여 하나의 파일 번들로 묶은 후 배포 디렉토리 안에 main.js파일 로 생성 시켜줍니다. 우리는 이 과정을 흔히 번들링이라고 합니다.

1
2
3
4
5
6
7
8
npx webpack
asset main.js 290 KiB [emitted] [minimized] [big] (name: main) 1 related asset
runtime modules 786 bytes 4 modules
modules by path ./node_modules/moment/locale/*.js 499 KiB 135 modules
./src/index.js 220 bytes [built] [code generated]
./node_modules/moment/moment.js 170 KiB [built] [code generated]
./node_modules/moment/locale/ sync ^\.\/.*$ 3.21 KiB [optional] [built] [code generated]

dist/main.js파일을 열어보면 webpack이 소스 코드를 최적화(uglify/minify) 해놓았음을 알 수 있습니다. 브라우저가 해석해야할 코드의 크기를 줄여주기 때문에 웹 어플리케이션의 성능이 좋아지며, 사람이 읽기 어렵기 때문에 약간의 보안적인 이점도 있습니다.

Webpack Bundle 참조하기

이제 index.html파일이 우리가 작성한 원래 소스 파일이 아닌 webpack이 만들어준 번들 파일이 참조하도록 수정합니다.

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
  <head>
    <title>Webpack Example</title>
  </head>
  <body>
    <script src="./dist/main.js"></script>
  </body>
</html>

다시 브라우져에서 index.html을 실행해보면 제대로 현재 시간이 표시되는 것을 확인할 수 있습니다. 이번에는 크롬 뿐만 아니라 익스플로러도 IE8이상이라면 정상적으로 작동하게 됩니다. 왜냐하면 웹팩이 Babel을 이용하여 ES6 문법으로 작성된 코드를 ES5 문법으로 변환(transpile)해주기 때문에 main.js파일을 ES6 문법을 지원하지 않은 브라우저도 해석할 수 있습니다.

javaScript 모듈화하기

이제 ES6 모듈 키워드(import,export)를 사용할 수 있으나 비단 외부 모듈을 사용할 때 뿐만 아니라 프로젝트를 모듈화할 때도 웹팩을 활용할 수도 있을 것입니다.

먼저 소스 디렉토리(src) 안에 time.js라는 자바스크립트 모듈 파일을 만들고 currentTime()함수를 index.js로 부터 옮겨옵니다. currentTime()함수에서 Moment.js를 사용하기 때문에 import하는 부분도 함께 옮겨와야 합니다. export 키워드를 사용해서 옮겨온 currentTime()함수를 외부에 노출 시킵니다.

  • time.js
1
2
3
4
5
import moment from "moment"

export function currentTime() {
  return moment().format("H:m:s")
}

index.js파일에는 제거된 코드를 대신해서 time.js모듈을 임포트하는 코드를 추가합니다.

  • index.js
1
2
3
4
5
import { currentTime } from "./time"

const div = document.createElement("div")
document.body.appendChild(div)
setInterval(() => (div.innerText = currentTime()), 1000)

다시 npx webpack커맨드를 실행해서 새로운 번들 파일을 만든 후 브라우저에서 index.html파일을 실행해보면 동일하게 현재 시간이 표시되게 됩니다.

소스 코드의 모듈 간의 의존성을 정리해보면 다음과 같으며, Webpack은 이러한 모듈간의 의존 관계를 트리로 구성하여 하나의 번들 파일로 제공하게 됩니다. 따라서 HTML 파일은 이 최종 번들 파일만을 참조할 수 있으며 이 것이 바로 웹팩이 우리에게 가져다주는 힘입니다.

1
index.js (최상위 내부 모듈) -> time.js (내부 모듈) -> moment.js (외부 모듈)

마치면서

웹팩의 기본 사용법을 보여드리기 위해서 본 포스트에서는 디폴트 설정 기준으로 webpack커맨드를 직접 사용해서 번들을 만들었습니다. 하지만 대부분이 경우에는 webpack.config.js라는 설정 파일을 사용하여 웹팩을 사용합니다.

This post is licensed under CC BY 4.0 by the author.