본문 바로가기
javascript

CommonJS / ES 모듈 로딩 방식

by 초특급하품 2020. 3. 29.

모르고 사용하다가는 여러 모듈을 가져다 쓸 때 헷갈릴 수 있어서 가장 기본적인 방법부터 복습해보았다.
typescript를 사용하면 typescript의 기능도 섞여있기 때문에 눈에 잘 안 보이는 경우가 있으니 주의하면서 정리해봤다. tsconfig.jsoncompilerOptions"target": "ES2017" 로 두고 import/export 하는 방법은 다음과 같다.

 

module.ts

const obj = { a: 10, b: 20 }
const func = (x: number) => x*2
const name = 'myName'

export default obj
export { func, name }

 

export로 해당 멤버를 외부로 노출시키는데 default 키워드를 추가하면 import할 때 키워드 없이 바로 받아오게 할 수 있다. 의미상 당연히 모듈 당 하나밖에 선언할 수 없다. 다른 멤버들은 {}로 묶어 노출시킨다.

 

main.ts

import objRename, { func, name as myname } from './module'

console.log(objRename, func(3), myname)

 

 

import 할 때 objRename처럼 바로 받으면 해당 모듈에서 default로 노출된 멤버를 받아온다. default라는 키워드 덕분에 이름을 일치시킬 필요는 없다. 나머지 멤버들은 마찬가지로 {}로 묶어 받아오고 이때는 이름을 일치시켜 가져온다. as로 받아온 후 바꿀 수는 있다.

 

특정 멤버를 지칭해서 가져오지 않고 *로 모듈 전체를 가져올 수도 있다. as로 alias를 설정하고 나머지 멤버는 위와 같은 규칙으로 참조하면 된다. default로 선언된 obj는 여기서도 마찬가지로 기본이기 때문에 obj라는 이름을 쓰지 않고 .default로 바로 참조된다.

 

import * as moduleA from './module'

console.log(moduleA.default, moduleA.func(3), moduleA.name)

 

 

결과부터 확인해보면 아래와 같이 빌드 후 실행해보면 예상한 결과가 나온다.

 

$ node_modules/.bin/tsc && node src/main.js 
{ a: 10, b: 20 } 6 'john'

 

 

결국 실행은 js이니까 빌드된 .js 파일도 확인해보자. 다른 부분은 제외하고 export 하는 부분만 보면 .ts로 작성한 문법과 비슷하게 바뀌어있다.

 

...
exports.func = func;
exports.name = name;
exports["default"] = obj;

 

 


 

 

이렇게 끝내면 좋겠지만 javascript의 모듈 세계는 오랜 세월의 흔적이 남아있어 깔끔하지 않다.
예를 들어 module.js 파일에서 아래와 같이 CommonJS방식으로 export 된 경우 문제가 발생한다.

 

const obj = { a: 10, b: 20 }

module.exports = obj

 

.js로 빌드된 결과물도 module.exports = obj; 와 같아서 위의 예시와 같이 import는 할 수 없고, CommonJS에 맞게 require문법을 사용해서 가져와야 한다.

 

import objRename = require('./module')

console.log(objRename)

 

하지만 이렇게 해결한다는 것은 사용하려는 모듈이 CommonJS / ES 모듈 중 어떤 방식으로 export 했는지 확인해야 하는 번거로움이 있다. 이를 typescript에서는 신경 안 써도 되게 해주는 옵션이 있다. "esModuleInterop": true를 추가하면 마법처럼 모듈 타입을 구분해주는 코드로 변환되어 일관성 있게 참조하며 사용할 수 있다.

 

import objRename from './module'

console.log(objRename)

'javascript' 카테고리의 다른 글

React class vs function component 차이점  (0) 2020.05.17
Typescript 타입 정의 파일  (0) 2020.03.29
ES8의 async와 await  (0) 2019.10.16
ES6의 Promise  (0) 2019.10.16
ES6의 Iterator와 Generator  (0) 2019.10.16

댓글