Module
분리된 코드 조각
시스템을 이루는 논리적인 일부분
Bundling
'묶는다'는 뜻.
기능별로 모듈화 했던 파일들을 하나로 묶어주는 작업을 말한다.
Bundler
여러 개의 파일을 묶어주는 도구.
Webpack, Borserify, Parcel 등이 있음
배경
// hello.js
var word = 'Hello';
// world.js
var word = 'World';
<html>
<head>
<script src="./source/hello.js"></script>
<script src="./source/world.js"></script>
</head>
<body>
<div id="root"></div>
<script>
document.querySelector('#root').innerHTML = word;
</script>
</body>
</html>
위와 같이 두 js 파일에서 동일한 word라는 변수명을 사용했을 때, 두 변수가 충돌하고 마지막으로 호출한 js파일 선언된 word만 적용된다.
이때 word는 전역 변수.
- 전역 스코프를 오염
- 예측하기 어려워짐
코드의 규모가 점점 커지고, 협업의 규모가 커지게 되면 이런 상황은 심각한 문제가 된다.
이러한 문제에 대응하기 위해
클로저의 원리를 이용한 즉시실행함수 등으로 모듈 구현
✅ 즉시 실행 함수 표현(IIFE, Immediately Invoked Function Expression)
(function() {
// 코드
})()
- 정의되자마자 즉시 실행
- 내부에 정의된 변수는 외부 범위에서 접근 할수 없음
- 변수에 할당 시, 함수는 저장되지 않고 함수의 결과값만 저장
var textWord = (function() {
var word = 'Hello'
return word
})()
textWord // 'Hello'
하지만 JS를 브라우저에 국한되지 않은 범용적인 언어로 사용하고자하는 움직임이 나타남
이를 위해 다른 라이브라이나 모듈을 적용시킬수 있는 호환성. 즉, 표준이 필요해짐.
👉 모듈화에 필요한 것
- 스코프 : 각 모듈은 독립적인 스코프를 가져야함
- 정의 : 모듈을 생성할 수 있어야햠
- 사용 : 정의된 모듈을 사용할 수 있어야함
✅ CommonJS, AMD 등장
CommonJS
- 모든 파일이 로컬에 존재하여 바로 불러있음을 전제로 함
- 동기적
- 대표적으로 Node.js에서 사용
- exports : 모듈을 생성
- require() 함수 : 모듈 import
module.explorts
require('./hello.js')
AMD(Asynchronous Module Definition)
- 비동기로 로딩되는 환경에서 모듈을 사용하는 것이 목표 (브라우저 내)
- define함수가 스코프의 역할을 함
/******
* id : 모듈을 식별할 인수
* dependencies: 모듈의 의존성을 나타내는 배열
* factory : 모듈의 실제 구현
******/
// 모듈 정의
define(id?, dependencies?, factory);
require([modulePath], function(module)(){
// 모듈로 사용할 코드
})
❗️ES2015(ES6)에서 모듈(module)이라는 것을 도입했다.
✅ Module (ES2015)
// hello.js
var word = 'Hello';
export default word;
여기서 word는 hello.js안에서만 유효함
// world.js
var word = 'World';
export default word;
여기서 word는 world.js안에서만 유효함
<html>
<head></head>
<body>
<div id="root"></div>
<script type="module">
import hello from "./source/hello.js";
import world from "./source/world.js";
document.querySelector('#root').innerHTML = hello + '' + world;
</script>
</body>
</html>
그래도 부족하다.
규모가 커질 수록 수많은 import를 하게 되는데 이는 서버 접속에 많은 비용을 요한다.
* 개발자도구에서 'network'패널 확인
✅ Bundler가 사용되기 전의 문제점
- import/export는 구형 웹브라우저에서 동작하지 않음
- 프로젝트 규모가 커질 수록
- 서버와의 접속이 많을 수록 애플리케이션은 느리게 로딩됨. (네트워크 부하 발생)
- 서로 다른 패키지들이 서로 같은 변수나 함수를 사용하면서 예상하지 못한 충돌이 발생.
Bundler 종류
✅Webpack
- 가장 대표적인 번들러
- webpack이란?
- 한글자를 수정해도 번들을 새로 만듦
✅ Rollup.js
- 모듈 번들러
작은 코드 조각을 라이브러리나 애플리케이션과 같이 더 크고 복잡한 것으로 컴파일하는 JavaScript용 모듈 번들러
- 번들화 ≠ 무조건적인 용량 축소
코드와 종속관계인 라이브라리를 정적으로 분석 후, 최소한의 것만 번들링 - ESM으로 설정파일 작성 (export/import)
- CommonJS 모듈, AMD 모듈 및 IIFE 스타일 스크립트와 같은 기존 지원 형식으로 다시 컴파일할 수 있음
✅ Parcel
불꽃 튀게 빠르고 설정이 필요 없는 웹 애플리케이션 번들러
- Parcel 공식사이트
- webpack에 비해 빠름
- zero-configuration : 설정이 필요없음
- 자세한 에러메세지 제공
- 동적 import()문을 사용해서 출력 번들을 분할. 초기 로드시 필요한 것들만 로드할 수 있음
- 파일시스템 캐시 : 재시작 후에도 빠른 리빌드
최초 빌드 후, 두 번째 빌드부터 빌드 속도가 빨라짐
✅ Snowpack
"unbundled during development" 개발중에 번들링을 하지 않는다
- 모듈 번들러 아님. 빌드 도구
- 빠른 빌드 속도 - 변경 사항이 브라우저에 즉시 반영
- 번들 과정이 없음. 필요시 webpack이나 rollup.js등을 사용할 수 있음
- 캐시를 사용해 동일한 파일(변경없는 파일)을 두 번 빌드하지 않음
- 브라우저에서 JavaScript의 기본 모듈 시스템(ESM)에 의해 구동
참고자료
생활 코딩 webpack
INGG. 블로그 [JS] Webpack을 쓰는 이유
Rollup.js https://rollupjs.org/
Snowpack https://www.snowpack.dev/
Parcel https://parceljs.org/
blog.jakoblind.no - Parcel vs webpack
'D.evelop > Bundler' 카테고리의 다른 글
[Webpack] 웹팩이란? (0) | 2021.12.15 |
---|
댓글