노드 ECMAScript 모듈, 다이나믹 임포트, top level await
ECMAScript 모듈(ES 모듈)은 공식적인 자바스크립트 모듈 형식이다.
노드에서는 아직까지 CommonJS모듈을 많이 쓰긴 하지만 ES 모듈이 표준으로 정해지면서 점점 ES모듈 사용 비용이 늘어나고 있다.
//var.mjs
export const odd = 'MJS 홀수';
export const even = 'MJS 짝수';
exports.odd로 썼던 문법이 위와 같이 바뀐 것을 볼 수 있다.
//func.mjs
import {odd, even} from './var.mjs';
function checkOddOrEven(num) {
if (numm % 2) {
return odd;
}
return even;
}
export default checkOddOrEven;
불러올때는 import from 으로 불러오는 것을 볼 수 있다.
또한 마지막 줄에 export default라고 되어 있는데 이건 module.exports 와 동일한 것이다.
//index.mjs
import {odd, even} from './var.mjs';
import checkNumber from './func.mjs';
function checkStringOddOrEven(str) {
if (str.length % 2) {
return odd;
}
return even;
}
console.log(checkNumber(10));
console.log(checkStringOddOrEven('hello'));
export default로 내보낸 것은 반드시 같은 이름이어야 하는 것은 아니다. 이름이 달라도 되는 것을 볼 수 있다.
default export : 이름이 반드시 같을 필요는 없음.
name export : 이름이 반드시 같아야 함.
ES 모듈의 import 나 export defult는 함수나 객체가 아니라 문법 그 자체이다.
require는 함수 exports는 객체이기 때문에 핸들링이 가능했지만 import나 export default는 예약어기 때문에 핸들링이 불가능하다.
또한 실행할 때 확장자 명을 생략할 수 없다.
다이나믹 임포트
조건부로 모듈을 불러오는 것을 다이나믹 임포트라고 한다.
ES모듈에서는 다이나믹 임포트가 되지 않는다.
CommonJS에서는 된다. 이 점을 이용해 다이나믹 임포트를 해보면 다음과 같다
//dynamic.js
const a = false;
if (a) {
require('./func');
}
console.log('성공');
if문 안에 require로 func를 읽는데 조건 a가 false여서 if문이 실행되지 않아 require는 실행이 되지 않았다.
//dynamic.mjs
const a = false;
if (a) {
import './func.mjs';
}
console.log('성공'); //애러
ES 모듈에서는 if문 안에서 import 하는 것이 불가능 하다. import 문은 문서의 최상단에 위치해야 하기 때문이다.
물론 ES 모듈에서도 다이나믹 임포트를 사용 할 수 있다.
//dynamic.mjs
const a = true;
if (a) {
const m1 = await import('./func.mjs');
console.log(m1);
const m2 = await import('./var.mjs');
console.log(m2);
}
import 라는 함수를 사용해서 모듈을 동적으로 불러올 수 있다.
import는 Promise를 반환해서 await이나 then을 붙여햐 한다.
export default의 경우 import할 때도 default라는 속성 이름으로 import 된 것을 볼 수 있다.
CommonJS 모듈에서 module.exports한 것도 default라는 이름으로 import 된다.
top level await
await a();
원래는 이렇게 하면 실행이 되지 않는다.
기본적으로 await을 사용하려면 async 함수로 감싸줘야 했다.
async function f() {
await a();
}
하지만 최상단에서 실행한다는 가정하에 ES 모듈에서 await a() 를 async 함수로 감싸지 않고 실행이 가능하다.