ES6 module 의 특징
앞선 문서에서 ES6 는 아래와 같은 특징을 지니게 되었다고 했습니다.
- CommonJS 와 유사하게, 모듈 간의 순환 참조를 지원합니다.
- AMD 와 유사하게, 비동기 module import 를 지원합니다.
- 정적 모듈 구조를 가집니다.
- 문법 구조가 단순합니다.
이 특징들에 대해 간단히 알아봅시다.
CommonJS 와 유사하게, 모듈 간의 순환 참조를 지원합니다.
순환 참조는 다음과 같은 상황을 뜻합니다.
- 모듈 A, B 가 있을 때, A 가 B 를 참조하고, B 가 A 를 참조하는 상황
- 모듈 A, B, C 가 있을 때, A 가 B 를 참조하고, B 가 C 를 참조하고 C 가 A 를 참조하는 상황
해당 상황은 피해야 하는 상황이지만 불가피하게 발생하는 경우가 있습니다.
예를 들어, DOM 트리에선 부모 노드가 자식 노드를 참조하고 자식 노드가 부모 노드를 참조하게 됩니다. 대규모 애플리케이션에선 리팩토링 도중에 이와 같은 상황이 발생하는 경우가 있습니다. AMD 는 이를 지원하지 않았지만, ES6 모듈 시스템은 이를 지원하기 때문에 시스템 상에서 오류가 발생하지 않습니다.
AMD 와 유사하게, Asynchronous Loading 을 지원합니다.
CommonJS 는 여러 모듈을 Import 하면 모든 모듈이 로드될 때까지 실행을 blocking 하였습니다. 이는 비교적 빠른 속도를 가진 파일 시스템에선 큰 문제가 되지 않았으나, 브라우저의 경우 네트워크 환경에 따라 다소 느릴 수 있기 때문에 이와 같은 방식은 사용성에 저해를 가져올 수 있었습니다.
AMD 에선 이를 여러 모듈을 Import 하면 먼저 로드되는 모듈 순서대로 동작을 수행할 수 있게 하였습니다. 이를 Asynchronous Loading 이라고 합니다. ES6 에서도 Asynchronous Loading 을 지원합니다.
정적 모듈 구조를 가집니다.
ES6 모듈 시스템은 정적인 구조를 가집니다. 이 말은 ES6 에서 모듈을 항상 top level 에서 import 해야 함을 의미하며 조건문 내부에서 import 구문을 사용할 수 없음을 뜻합니다.
만약, 모듈을 동적으로 로드하고 싶다면 import() 를 사용해야 합니다. 이와 같은 구조를 택함으로써 다음과 같은 장점을 취할 수 있습니다.
Tree Shaking 을 할 수 있습니다.
import 대상을 빠르게 lookup 할 수 있습니다.
예를 들어, CommonJs 의 경우
// commonJS
var lib = require('lib');
lib.someFunc(); // => 동적으로 lib 에 someFunc 이 있는지 lookup 하고 접근합니다.ES6 에서 import 하는 경우 어떤 대상이 export 되는지 정적으로 알 수 있기 때문에, lookup 의 속도가 줄어듭니다.
import lib from 'lib';
lib.someFunc(); // => 정적으로 lib 에 someFunc 의 유무를 알고 접근합니다.
Typing 을 할 수 있습니다. 정적으로 Typing 을 분석하기 위해선 정적인 모듈 구조가 필수입니다.
다음 문서는 ES6 모듈 시스템의 문법적인 특징을 기술하겠습니다.