노드

노드 ECMAScript 모듈, 다이나믹 임포트, top level await

포칼이 2023. 4. 11. 15:45

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 함수로 감싸지 않고 실행이 가능하다.