Skip to content

Instantly share code, notes, and snippets.

@rabelais88
Created January 29, 2021 10:21
Show Gist options
  • Save rabelais88/d099f9f8ea2f70d348a4c5b0819a6c76 to your computer and use it in GitHub Desktop.
Save rabelais88/d099f9f8ea2f70d348a4c5b0819a6c76 to your computer and use it in GitHub Desktop.
웹팩 이해하기

번들러 이해하기

by 박성렬

웹상에서의 모듈이란?

자바스크립트는 1995년는 처음 등장한 이래로 아주 간단한 형태로만 유지되었습니다. 통신 대역폭도 크지 않았고, 웹은 인터랙션이 거의 없는 하이퍼링크 위주의 단순한 텍스트였습니다. 따라서 큰 프로그램을 만들다 보면 아주 당연히 필요하게 되는 모듈의 개념이 웹(브라우저)상에는 구현되어있지 않았습니다. 인터랙티브 웹의 태동기에 이를 외부적으로 구현한 라이브러리가 *AMD, Common.js(혹은 requirejs)*에 해당합니다.

// AMD
define(myModule);
// Common.js(require.js)
var myModule = require('./myModule');

그러나 점차 시간이 지나면서 통신의 대역폭이 커지고, 웹상에서 돌아가는 프로그램들의 크기가 커졌으며, 좀더 일반적인 프로그래밍 언어에서 볼 수 있는 형태의 모듈이 자바스크립트에서도 필요하게 되었습니다.

import myModule from './myModule';

아직도 브라우저에서는 이를 정식으로 지원하지 않지만, 최소한 Node.js상에는 아주아주 최근에 지원이 시작되었고, 그 이전까지 모듈화는 모두 번들러를 통해 이루어졌습니다.

번들러의 역할은 즉 모듈로 잘게 쪼개져 있는 파일을 하나의 묶음(package)로 묶어 주는 것입니다.

웹팩 배우기

위의 공식 문서에 따라 웹팩의 웹팩 돌려보기페이지에 접근합니다. 해당 내용은 github으로도 전달 드렸습니다.

# 폴더 내용 다운받아 실행할 준비 하기
git clone https://github.com/rabelais88/lesson-webpack

링크 드린 github이 담고 있는 내용은 단순히 웹팩 돌려보기 페이지에 있는 일부 코드를 복사 붙여넣기 한 것입니다. 여러분들이 할 것은, .html.js형태로 되어있는 단순한 웹 문서 파일을, 실제 배포가 가능하고, 다른 모듈을 다운로드하여 결합할 수 있는 형태로 만드는 것입니다.

폴더 구조는 이렇게 되어있습니다.

.
├── README.md
└── src
    ├── app.js
    └── index.html

이 프로그램을 번들링하지 않고 그대로 로컬 실행환경에서 돌려보려면, 아래의 명령어를 입력하면 됩니다.

npx http-server ./src

이 뜻은, ./src폴더 내부의 파일을 localhost의 임의의 포트로 송출(이를 보통 서빙serving이라고 표현합니다)하겠다는 뜻입니다.

명령어를 실행 시킨 후, 화면에 아래와 같은 내용이 나오면, 주소를 그대로 복사하여 브라우저에 입력합니다.

$ npx http-server ./src
npx: installed 23 in 1.801s
Starting up http-server, serving ./src
Available on:
  http://127.0.0.1:8080
  http://192.168.1.171:8080
Hit CTRL-C to stop the server

여기서 http://127.0.0.1:8080또는 localhost:8080을 입력합니다. 경우에 따라 8080포트가 이미 사용중일 경우는 다른 포트를 사용하라고 할 수도 있습니다.

접근해보면 브라우저에 index.html의 내용이 표시됩니다. 주소에 아래의 내용을 입력하면 자바스크립트 소스코드에도 접근할 수 있습니다.

localhost:8080/app.js

즉, 단순히 파일을 띄우는 기능 이외에는 아무것도 하지 않습니다.

index.html의 내용을 아래와 같이 수정하여, hello webpack이라는 메시지가 브라우저에 나타나도록 수정합니다.

<script src="./src/app.js"></script>
<!-- 수정 후-->
<script src="app.js"></script>

내용을 저장하고 브라우저를 새로고침하면 잘 돌아가는 것을 알 수 있습니다. 이것을 손으로 직접 고친 이유는, 이렇게 파일의 참조 위치를 수정하는 것 또한 웹팩이 하는 일이기 때문입니다. 지금은 웹팩이 제대로 설정되어있지 않기 때문에, 이를 수동으로 바꿔주는 일을 했습니다.

여기에 yarn 또는 npm을 사용하여 lodash를 설치해 봅니다.

yarn add lodash
# 또는
npm install lodash
# 또는
npm i lodash

그리고 나서 이를 불러올 수 있도록 app.js의 상단에 아래와 같은 코드를 추가해봅니다.

import lodash from 'lodash';
console.log(lodash);

브라우저를 새로고침한 뒤, 개발자 도구(Ctrl+F12 또는 Command+Option+I)를 눌러보면 콘솔에서 import관련 오류가 찍히는 것을 확인할 수 있습니다.

즉 패키지에 대한 번들링이 이루어지지 않았기 때문입니다. 우선 방금 추가한 import 구문을 주석처리합니다. 이를 웹팩을 통해 번들링해야하기 때문에, 웹팩을 설치합니다.

yarn add -D webpack webpack-cli

그리고 폴더에 웹팩 설정파일(webpack.config.js)을 추가합니다. 파일 구조는 아래와 같이 되어야 합니다.

.
├── README.md
├── src
│   ├── app.js
│   └── index.html
├── package.json
├── webpack.config.js # 수동으로 추가할 파일입니다.
└── yarn.lock

설정 파일의 기본 위치, 파일명은 관련 문서를 참조할수도 있습니다.

webpack.config.js의 내용은 아래와 같이 되어야합니다.

const path = require('path'); // 디렉토리 구조가 OS별로 다르기 때문에, 이를 자동으로 보완하기 위한 Node.js의 library입니다.

module.exports = {
  entry: './src/app.js', // 프로그램이 시작될 첫 모듈(entrypoint) 입니다.
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'dist'), // __dirname === $(pwd), ./dist 폴더에 결과물을 내놓겠다는 뜻입니다.
  },
};

세세한 차이는 있지만, 번들링 과정은 다른 프로그래밍 언어의 컴파일 과정과 유사하기 때문에 번들링을 컴파일로 표현하기도 합니다. 다른 프로그래밍 언어에 compile time, runtime이 있듯 번들링에도 비슷한 개념이 있습니다.

웹팩의 설정파일은 자세히 보시면 .json이 아니라 .js인데, 즉 컴파일 과정이 node.js로 된 일종의 프로세스라고 볼 수 있습니다.

여기서 require를 쓰는 이유도, node가 비교적 최근에야 import를 지원하기 시작해서 호환성을 위해 require사용을 추천하기 때문입니다. 즉, runtime과 compile time 의 import 방식이 다른 이유를 유념하면서 작업하시면 더 좋습니다. 런타임: 웹(브라우저)에서 실행되는 환경 컴파일 타임: node.js를 통해 웹팩이 번들링(컴파일)하는 환경

이제 아래와 같이 입력하면, ./dist폴더가 생성되면서 그 안에 자동으로 컴파일된 결과가 나타납니다.

yarn webpack
# 또는
npm webpack

생성된 dist/main.js파일을 들여다 보면, 원본 app.js파일과 약간 달라진 것을 알 수 있습니다.

document.body.appendChild(function(){const e=document.createElement("div");return e.innerHTML=_.join(["Hello","webpack"]," "),e}());

이렇게 된 이유는, 웹팩이 자바스크립트 소스를 웹에서 돌아가기 적합한 형태로 사이즈를 줄이기 때문입니다. 마치 컴파일 과정에서 human readable 코드를, 기계어로 번역해 주는 것과 유사합니다. 이를 웹에서는 uglifying이라고 표현합니다. 일반적인 포멧에서 벗어났기 때문입니다.

그리고 완성된 코드를 돌려볼 수 있도록 ./dist폴더에 index.html파일을 복사하여 아래와 같이 수정합니다.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Getting Started</title>
  </head>
  <body>
    <script src="main.js"></script>
  </body>
</html>
We also need to adjust our package.json file in order to make sure we mark our package as private, as well as removing the main entry. This is to prevent an accidental publish of your code.

그리고 나서 아래의 커맨드로, 배포폴더를 서빙합니다.

npx http-server ./dist

원래 보았던 결과를 그대로 또 보실 수 있습니다. 즉, 내용물은 uglifying 되었을 지언정, 오히려 브라우저는 별 문제 없이 읽어들인다는 것을 알 수 있습니다.

이제 준비가 다 끝났으므로, 아까 주석처리한 내용을 다시 원상복귀하고 다시 컴파일 커맨드를 입력합니다.

yarn webpack

이제 import커맨드가 정상 동작함을 알 수 있습니다.

기억해야할 것

웹팩은 일견 복잡해 보이지만, 동작 방법이나 구조는 매우 단순합니다. 즉, 브라우저에서 열어볼 수 있는 형태의 .html, js파일을 내보내는게 가장 큰 목적이고, 코드 및 자원(.jpg, .gif, .css 등)을 브라우저에 최적화시킵니다.

Vue-cli와 CRA(Create React App) 모두 소스코드가 감추어져 있기 때문에 이같은 사실을 파악하기 어렵지만, 실제로 node_modules폴더에 설치된 내용을 직접 분해하거나, eject명령어를 통하여 설정파일을 외부로 반출하게 되면 위에 설명드린 웹팩 설정 내용이 나타남을 알 수 있습니다.

모던 자바스크립트의 개발도구는 이처럼 웹팩에 상당한 부분을 의지하고 있습니다. 따라서 훌륭한 프론트엔드 개발자가 되기 위해서는, 웹팩을 완전히 이해하지 못하더라도 어떻게 웹팩이 돌아가는지 이해할 필요가 있습니다.

물론 TODO수준의 앱을 만드는데 필요한 내용은 아닙니다. 그러나 실무에 투입되신 후에는 생각보다 운영진 또는 CTO가 아주 까다로운 요청을 (e.g. SEO를 위해 페이지 사이즈를 줄여달라, 접근할 수 있는 URL을 고쳐달라 등) 할 수도 있고, 이를 맞추기 위해서는 webpack을 무조건 이해하고 있으셔야 합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment