목차
· 들어가며
· CJS란?
· AMD란?
· UMD란?
· ESM란?
들어가며
처음 자바스크립트는 모듈을 가져오거나, 내보내는 방법이 없어 하나의 파일에 모든 기능들이 들어가야했다. CJS, AMD, UMD, ESM이 등장 후에는 모듈로 개발하고, 배포할 수 있게 되었으며 이번 포스트에서는 모듈화 개발을 할 수 있게 해준 CJS, AMD, UMD, ESM이 무엇인지에 대해 알아보려고 한다.
모듈(module)이란?
모듈이란 여러 기능들에 관한 코드가 모여있는 하나의 파일로 다음과 같은 것들을 위해 사용한다.
유지보수성 : 기능들이 모듈화가 잘 되어있다면, 의존성을 그만큼 줄일 수 있기 때문에 어떤 기능을 개선한다거나 수정할 때 훨씬 편하게 할 수 있다.
네임스페이스화 : 자바스크립트에서 전역변수는 전역 공간을 가지기 때문에, 코드의 양이 많아질수록 겹치는 네임스페이스가 많아질 수 있다. 그러나 모듈로 분리하면 모듈만의 네임스페이스를 갖기 때문에 그 문제가 해결된다.
재사용성 : 똑같은 코드를 반복하지 않고, 모듈로 분리시켜서 필요할 때마다 사용할 수 있다.
CJS(CommonJS) 란?
우리가 자바스크립트를 사용해보았다면, 평소에 많이 접해왔던 이름 중 하나이다. 이름의 `Common`에서 알 수 있듯, 자바스크립트를 브라우저에서뿐만 아니라 범용 언어로 사용할 수 있도록 하겠다는 의지를 가진 워킹 그룹이다.
코드 예제
// 아래와 같이 require을 통해 package/lib 모듈을 변수에 담을 수 있다.
var lib = require('package/lib');
// 가져온 모듈을 아래와 같이 사용할 수 있다.
function foo() {
lib.log("Hello, World")
}
// foo 함수를 다른 파일에서 사용할 수 있도록, 다른 모듈로 추출될 수 있다.
exports.foobar = foo;
CJS는 `동기` 특성을 가지고 있다.
CommonJS는 동기로 동작하는 특징을 가지고 있다.
var foo = require('foo');
var bar = require('bar');
foo.log("It is foo");
bar.log("It is bar");
CommonJS는 동기적인 특징으로 서버사이드에 사용하기 용이하다. (CommonJS의 첫 이름은 ServerJS 였다고 한다) 현재 Node.js가 CommonJS를 채택하여 사용을 하고 있다.
AMD(Asynchronous Module Definition)란?
CommonJS는 모든 파일이 로컬 디스크에 있어 필요할 때 바로 불러올 수 있는 상황을 전제로 한다. 즉 동기적인 동작이 가능한 서버 사이드 자바스크립트 환경을 전제로 한다. 브라우저에서 이런 방식은 필요한 모듈이 모두 다운로드 될 때까지 아무것도 할 수 없는 상태가 되어 치명적인 단점이 된다.
AMD 워킹 그룹은 비동기 상황에서 자바스크립트 모듈을 사용하기 위해 CommonJS에서 함께 논의하다 합의점을 이루지 못하고 독립한 그룹이다. CommonJS가 자바스크립트를 브라우저 밖으로 꺼내기 위해 탄생된 그룹이고, AMD는 브라우저에 중점을 둔 그룹이다.
// 종속성을 갖는 모듈인 'package/lib'을 모듈 선언부의 첫 번째 파라미터에 넣으면, 'package/lib'은 콜백 함수의 lib 파라미터 안에 담긴다.
define(['package/lib'], function(lib) {
// 로드된 종속 모듈을 아래와 같이 사용할 수 있다.
function foo() {
lib.log("Hello, World");
}
// 생성된 foo 함수는 리턴을 통해 foobar라는 이름의 다른 모듈로 추출될 수 있다.
return {
foobar: foo;
}
});
선언된 모듈들을 아래의 require 키워드로 사용할 수 있다.
require(['package/myModule'], function(myModule) {
myModule.foobar();
});
AMD는 `비동기` 특성을 가지고 있다.
브라우저는 네트워크를 통해 모듈들을 내려받기 때문에, 비동기적으로 동작을 해야한다. AMD 이름의 `Asynchronous`에서 알 수 있듯, AMD는 비동기 모듈에 대한 표준안을 다루고 있다. AMD는 비동기적인 특징으로 클라이언트 사이드 개발에 적합하다.
UMD(Universal Module Definition)란?
AMD와 CommonJS 두 그룹으로 나누어지다보니, 서로 호환되지 않는 문제가 발생하게 된다. 이것을 해결하기 위해 나온 것이 UMD이다. UMD는 디자인 패턴에 더 까가우며, AMD와 CommonJS, window에 추가하는 방식까지 모두 가능한 모듈을 작성하는 방식이다.
- 모듈 로더를 확인하는 즉시 실행 함수 (IIFE) : 이 함수는 root(전역 범위)와 factory(모듈을 선언하는 함수) 2개의 파라미터를 가진다.
- 모듈을 생성하는 익명 함수 : 이 함수가 즉시 실행 함수의 2번째 파라미터로 전달된다.
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['exports'], 'b'], factory);
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// commonJS
factory(exports, require('b'));
} else {
// Browser globals
factory((root.commonJsStrict = {}), root.b);
}
} (this, function (exports, b) {
exports.action = function() {};
}));
exports와 module이 존재하면 commonJS 방식으로, define이 함수이고 define.amd가 존재할 경우에는 AMD 방식으로, 그것이 아니라면 window 객체에 모듈을 내보낸다.
UMD는 여러 모듈 로더에서 사용이 가능하다는 특징을 가지고 있다.
UMD의 특징은 AMD와 commonJS 모두 사용 가능하다는 이점을 가지고 있다. AMD는 클라이언트 사이드에서 많이 사용되고, commonJS는 서버 사이드에서 많이 사용되기 때문에, UMD를 사용하면 두 개의 모듈을 따로 만들 필요가 없게 된다.
ESM(ECMAScript Module)란?
ES6에 추가된 자바스크립트 모듈 기능이다.
import lib from 'package/lib';
function foo() {
lib.log("Hello, World");
}
export {
foobar: foo
};
ESM의 특징은 자바스크립트 자체 모듈 시스템이라는 것이다.
ESM은 ECMAScript에서 지원하는 자바스크립트 공식 모듈 시스템이다. 아직 브라우저에서 import와 export를 지원하지 않아 번들러와 함께 사용을 해야한다. <script> 태그에 type="module"을 선언하면 자바스크립트 파일은 모듈로 동작을 한다. 이때, 모듈이라는 것을 명확히 알기 위해서는 mjs 확장자를 사용하도록 권장한다.
<!DOCTYPE html>
<html>
<body>
<script type="module" src="foo.mjs"></script>
<script type="module" src="bar.mjs"></script>
</body>
</html>
/** foo.mjs */
var x = 'foo';
console.log(x); // foo
// (변수 x는 전역 변수가 아니며, window 객체의 프로퍼티도 아니다)
console.log(window.x) // undefined
/** bar.mjs */
// import 사용이 가능하다.
import test from './module/mjs';
console.log(test);
// 변수 x는 foo.mjs에서 선언한 변수 x와 스코프가 다른 변수이다.
var x = 'bar';
console.log(x); // bar
// 변수 x는 전역변수가 아니며 window 객체의 프로퍼티도 아니다.
console.log(window.x);
/** module.mjs */
const test = 'hello world!';
// export 사용이 가능하다.
export default test;
type="module"을 사용하면 해당 파일에 import와 export 사용이 가능하다. 또한 파일마다 독립적인 스코프를 가져 foo.mjs 파일과 bar.mjs 파일의 window는 서로 공유되지 않는다. type="module"은 아직 많은 브라우저에서 모듈 시스템을 지원하지 않기 때문에 webpack이나 rollup 등의 번들러를 사용하는 것이 좋다.
요약
- CJS(CommonJS) : 동기적인 특징으로 서버 사이드에서 사용하기 용이하다.
- AMD(Asynchronous Module Definition) : 비동기적인 특징으로 클라이언트 사이드에서 사용하기 용이하다.
- UMD(Universal Module Definition) : CJS와 AMD 모듀 사용 가능한 모듈을 만들기 위해 사용된다.
- ESM(ECMAScript Module) : 자바스크립트 공식 모듈 시스템이다.
- <script type="module" src=""></script>을 사용하여 브라우저에서도 모듈 시스템을 사용할 수 있다.
레퍼런스
댓글