자바스크립트를 서버에서 사용할 수 있게된 가장 큰 이유 중 하나는 모듈화가 가능해졌기 때문이다.
자바스크립트의 모듈화 명세를 만든 대표적인 그룹 중 'CommonJs'가 존재하고, CommonJS의 명세는 현재 node.js의 표준이 되었다.
node의 표준인 require와 module.exports가 있다.
하지만 ES6로 넘어오게 되면서 자바스크립트 자체에서 ES6 Module이라는 이름으로 모듈화가 지원되기 시작하였고 import와 export가 그것이다.
- 스코프(Scope): 모든 모듈은 자신만의 독립적인 실행 영역이 있어야 한다.
- 정의(Defintion): 모듈 정의는 전역객체인 export 객체를 이용.
- 사용(Usage): 모듈 사용은 require 함수를 이용
원래는 module.exports가 기존 사용법이었지만, 숏컷으로 exports가 생겼다.
exports는 module.exports를 가리키는 변수로써 그 사용을 도와주는 'helper'의 역할로 참조만 한다.
exports와 module.exports가 동일한 하나의 객체를 바라보고 있다는 뜻이다. 그래서 최종적으로 return 되는 것은 무조건 module.exports의 값이 되고, exports는 자연스럽게 무시된다. 기본적으로 2가지 규칙이 있지만, 특별한 상황이 아니라면 module.exports를 사용하는 것을 권장한다.
- 여러 개의 객체를 내보낼 경우, exports 변수의 속성으로 할당한다.
- 딱 하나의 객체를 내보낼 경우, module.exports 변수 자체에 할당한다.
유의할 점은 exports와 module.exports를 섞어서 사용하면 안된다는 것이다.
데이터를 외부로 내보내려면 module.exports 변수에 내보내고자 하는 데이터들을 담아 객체로 지정해주면 된다. 그러면 이것을 불러오는 쪽에서는 해당 객체에 접근하여 내보내진 데이터들을 사용할 수 있다.
module.exports = 128;
module.exports = { name: 'Elon', height: 180 };
exports.name = 'Elon';
exports = 'Elon'; // Not allowed
외부 모듈의 데이터를 불러오려면 require('경로') 함수의 반환 값을 변수에 대입하면 된다. require() 함수가 반환하는 것은 해당 모듈의 module.exports 객체이다.
const obj = require("./exportFile.js");
CommonJS와 마찬가지로 기본적으로 원하는 모듈을 내보내고 가져오는 것은 동일하다. 사용하는 키워드는 export와 import로 조금 더 직관적일 수 있다.
이러한 모듈 시스템을 브라우저에서 사용하려면 script 태그에 type='module' 어트리뷰트를 추가해야한다. 그러면 그 안에 작성된 자바스크립트 코드들은 ES6 기반 모듈 내보내기 및 불러오기 방식을 지원하게 된다. 이 때 불러오는 파일이 모듈임을 명확하게 하기 위해 <scirpt type='module'> 태그로 불러오는 자바스크립트 파일의 확장자는 mjs로 설정하도록 권장되고 있다.
기존 CommonJS의 방식보다 효율적이고 직관적으로 보이는 ES6 기반의 모듈 시스템은 몇몇가지 단점을 가지고 있다.
- IE를 포함한 몇몇 구형 브라우저는 ES6 모듈 시스템을 지원하지 않는다. (거의 다 지원함)
- 브라우저의 ES6 모듈 시스템을 사용하더라도 어차피 트랜스파일링이나 번들링은 필요하다.
- 아직 지원하지 않는 기능(Bare import 등)들이 꽤 존재한다.
- 점차 해결되고는 있지만 아직 몇가지 이슈가 존재한다.