Webpack

5 분 소요


👉 아래 글은 해당 포스트의 테스트를 수행하는데 도움을 줍니다.

0. 들어가면서

Java 언어를 주력으로 사용하는 백 엔드 개발자이지만, 일을 하다보면 프론트 엔드에 대한 이해도도 높아야한다고 느낍니다. 여태껏 프론트 엔드 관련 기술에 큰 관심이 없었지만, 최근 프로젝트에서 프론트 엔드 개발을 많이 접하면서 관심이 크게 높아졌습니다. 요즘 많이 사용하는 React 라이브러리나 Vue.js 프레임워크를 처음 접하면 Webpack, Babel 이라는 단어를 듣게 됩니다. 많은 글들을 찾아봤지만 해당 기술에 대한 정확한 개념이 잡히질 않습니다. 그래서 직접 정리해보았습니다. 이번 Webpack과 관련된 포스트를 시작으로 앞으로 프론트 엔드 기술과 관련하여 공부한 내용을 공유할 생각입니다.

1. Webpack

Webpack is a module bundler.

공식 홈페이지에서 Webpack을 모듈 번들러(module bundler)라고 소개하고 있습니다. 번들러(bundler)는 무엇인가를 한데 모아주는 것이라는 의미인데, 모듈(module)에 대한 감이 잘 잡히지 않습니다. 우선 모듈에 대한 개념부터 정리해보겠습니다.

1.1. 모듈(module)

Module from dictionary
any of a number of distinct but interrelated units from which a program may be built up or into which a complex activity may be analyzed.

보통 개발 분야에서 모듈이란 특정 기능을 수행할 수 있는 코드를 집약시켜놓은 것을 의미합니다. 간단한 기능을 수행하는 모듈을 모아서 더 복잡한 기능을 수행하는 모듈을 만들 수도 있습니다. 모듈은 자신만의 고유한 영역(scope)를 가지고 있는 것이 특징인데, 이전 Javascript 세상엔 모듈이라는 개념이 없었다고 합니다. 간단하게 예를 들어보겠습니다.

1.1.1. 모듈을 사용하지 않은 코드

hello.js
  • message 변수를 선언하고 ‘Hello’라는 문자열을 할당합니다.
var message = 'Hello';
world.js
  • message 변수를 선언하고 ‘World’라는 문자열을 할당합니다.
var message = 'World';
index.html
  • hello.js, world.js 파일을 사용하기 위해 스크립트(script) 태그(tag)로 선언합니다.
  • 스크립트 태그에 root ID를 가진 div 태그의 내부 HTML을 message 변수에 지정된 값으로 변경하는 코드를 작성합니다.
<!DOCTYPE html>
<html>
<head>
    <script src="./hello.js"></script>
    <script src="./world.js"></script>
</head>
<body>
    <div id="root"></div>
    <script>
        document.getElementById("root").innerHTML = message;
    </script>
</body>
</html>
브라우저 실행 결과
  • “World”가 출력됩니다.
  • 동일한 이름의 message 변수명이 hello.js, world.js 파일 모두에 존재합니다.
  • 아래 위치에 추가한 world.js 파일의 message 변수가 사용됩니다.

1.1.2. 모듈을 사용한 코드

위와 같은 현상을 전역 스코프(scope)가 오염되었다고 표현합니다. 많게는 수십 개의 Javascript 파일이 필요한 HTML 문서를 작성할 때, 다수의 Javascript 파일을 여러 명의 개발자가 나누어 작업했다면 변수 충돌 문제는 더 심각할 수 있습니다. 변수명의 충돌로 의도치 않은 버그가 발생할 가능성이 커집니다. 이번에는 모듈을 사용한 코드를 살펴보겠습니다.

hello.js
  • message 변수를 선언 후 객체에 담아서 이를 외부에 노출(export)합니다.
  • hello.js 파일을 모듈(module)로 만들어 외부에 제공한다는 것을 의미합니다.
var message = 'Hello';

export default {
    message: message
};
world.js
  • message 변수를 선언 후 객체에 담아서 이를 외부에 노출합니다.
  • world.js 파일을 모듈로 만들어 외부에 제공한다는 것을 의미합니다.
var message = 'World';

export default {
    message: message
};
index.html
  • 스크립트 타입을 module로 지정합니다.
  • hello.js 파일에서 제공하는 모듈을 hello라는 이름으로 입력(import)받습니다.
  • world.js 파일에서 제공하는 모듈을 world라는 이름으로 입력받습니다.
  • 스크립트 태그 안에 root ID를 가진 div 태그의 내부 HTML을 hello.message + world.message로 지정하는 코드를 작성합니다.
<!DOCTYPE html>
<html>
<head></head>
<body>
    <div id="root"></div>
    <script type="module">
        import hello from './hello.js';
        import world from './world.js';
        document.getElementById("root").innerHTML = hello.message + world.message;
    </script>
</body>
</html>
브라우저 실행 결과
  • “HelloWorld”라는 문자열이 출력됩니다.
  • 동일한 이름의 message 변수명이 hello.js, world.js 파일 모두에 존재하지만, 모듈 단위로 구분하여 사용할 수 있습니다.
  • 각 Javascript 파일을 모듈화하여 외부로 제공하였습니다.(export)
  • 필요한 Javascript 파일을 적절한 위치에 선언하여 사용하였습니다.(import)

1.1.3. type=”module” 키워드 사용시 유의점

type="module" 키워드를 사용한 모듈 기능은 모든 브라우저에서 사용 가능하진 않습니다. 관련된 정보는 https://caniuse.com/?search=module에서 확인할 수 있습니다.

이미지 출처, https://caniuse.com/?search=module


2. Webpack 사용

이번 포스트는 Webpack에 대해 정리하는 글이기 때문에 매우 불편한 방법으로 Webpack을 사용하였습니다. 다음 포스트에서 설정 파일을 이용하여 더 쉽게 Webpack을 사용하는 방법을 정리하겠습니다. 이제부터 작성한 모듈들을 Webpack을 사용하여 한데 모으는 작업을 진행하겠습니다. 이런 행위를 번들링(bundling)이라고 합니다.

2.1. Webpack 설치하기

사용하기 위해선 우선 설치를 해야합니다. npm 명령어를 통해 설치할 수 있습니다. npm이 없다면 Node.js를 우선 설치하시길 바랍니다.(https://nodejs.org/en/) PC 전역에서 사용할 수 있도록 -g 옵션을 두어 설치하였습니다.

$ npm install -g webpack webpack-cli

2.2. 엔트리 포인트(entry point) 만들기

An entry point indicates which module webpack should use to begin building out its internal dependency graph.

Webpack을 사용하기 위해선 시작 입구를 지정해줘야 합니다. 한데 모아 놓은 모듈들을 사용하기 위한 시작점이 필요한 것 입니다. Java 클래스의 public static void main(String[] args) 메소드와 비슷한 느낌이 듭니다. 이를 엔트리 포인트(entry point)라고 합니다.

index.js
  • hello.js, world.js 파일을 추가합니다.
  • root ID를 가진 div 태그의 내부 HTML을 hello.message + world.message로 지정하는 코드를 작성합니다.
import hello from './hello.js';
import world from './world.js';
document.getElementById("root").innerHTML = hello.message + world.message;

2.3. CLI(Command Line Interface)를 사용한 번들링(bundling)

설치한 Webpack을 사용하여 번들링을 수행하겠습니다. 우선 번들링 할 파일들이 위치한 디렉토리로 이동합니다.

$ cd <directory>

번들링 수행 전에 폴더를 보면 다음과 같은 파일들이 존재합니다.

$ ls -al
total 4
drwxr-xr-x 1 kang3 197609   0 Sep 15 06:25 ./
drwxr-xr-x 1 kang3 197609   0 Sep 15 05:56 ../
-rw-r--r-- 1 kang3 197609  68 Sep 15 05:19 hello.js
-rw-r--r-- 1 kang3 197609 130 Sep 15 06:02 index.html
-rw-r--r-- 1 kang3 197609 140 Sep 15 05:57 index.js
-rw-r--r-- 1 kang3 197609  68 Sep 15 05:19 world.js

다음과 같은 명령어를 수행합니다.

  • --entry 옵션 - 엔트리 포인트는 index.js 파일로 지정합니다.
  • --output-path 옵션 - 번들링한 파일은 현재 디렉토리에 만듭니다.
$ webpack --entry ./index.js --output-path ./
asset main.js 78 bytes [emitted] [minimized] (name: main)
orphan modules 136 bytes [orphan] 2 modules
./index.js + 2 modules 276 bytes [built] [code generated]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

webpack 5.52.1 compiled with 1 warning in 221 ms

번들링 수행 후 폴더를 보면 아래와 같이 main.js 파일이 만들어진 것을 확인할 수 있습니다.

$ ls -al
total 5
drwxr-xr-x 1 kang3 197609   0 Sep 15 06:28 ./
drwxr-xr-x 1 kang3 197609   0 Sep 15 05:56 ../
-rw-r--r-- 1 kang3 197609  68 Sep 15 05:19 hello.js
-rw-r--r-- 1 kang3 197609 130 Sep 15 06:02 index.html
-rw-r--r-- 1 kang3 197609 140 Sep 15 05:57 index.js
-rw-r--r-- 1 kang3 197609  78 Sep 15 06:28 main.js
-rw-r--r-- 1 kang3 197609  68 Sep 15 05:19 world.js

2.4. 번들링 파일 사용하기

hello.js, world.js 파일은 변경이 없으니 설명을 제외하였습니다. index.js 파일도 엔트리 포인트 설명과 동일하므로 제외하였습니다.

index.html
  • 번들링하여 만들어진 main.js 파일을 추가합니다.
<!DOCTYPE html>
<html>
<head></head>
<body>
    <div id="root"></div>
    <script src="./main.js"></script>
</body>
</html>
브라우저 실행 결과
  • 브라우저에 표시되는 문장은 동일합니다.
  • 이전 테스트와 다르게 필요한 자원이 main.js 파일 한 개입니다.
    • 이전 테스트 결과를 보면 다운로드 되는 자원이 hello.js, world.js 두 개입니다.

3. Webpack 사용시 얻는 이점

다음과 같이 정리할 수 있을 것 같습니다.

  • 변수 충돌 문제 해결 - 전역 스코프(scope)의 오염을 막을 수 있습니다.
  • 호환성 문제 해결 - type=module처럼 특정 브라우저에서 호환되지 않는 기능을 사용할 필요가 없습니다.
  • 자원 사용의 효율 개선 - 번들링을 통해 생성된 자원만 사용하면 되므로 자원에 대한 접근이 대폭 감소합니다.

CLOSING

처음 접할 때 많이 어려웠던 Webpack이라는 개념을 제가 이해하는 수준에서 정리하였습니다. Webpack 문서를 다짜고짜 읽기만 했을 때는 안 보였던 것들이 이제는 조금 더 이해가 되기 시작했습니다. 이 포스트가 저처럼 처음부터 어려운 내용을 쉽게 소화하지 못하는 분들에게 많은 도움이 되길바랍니다.

TEST CODE REPOSITORY

REFERENCE

카테고리:

업데이트: