
모듈은 애플리케이션을 구성하는 개별적 요소로서, 재사용 가능한 코드 조각을 말한다.
모듈을 구성하고, 이를 재사용하는 방법에 대해 알아보자.
모듈이 성립하기 위해서는 자신만의 파일 스코프(모듈 스코프) 를 가질 수 잇어야 한다.
모듈은 캡슐화되어 다른 모듈에서 접근할 수 있고, 각 모듈은 개별적 존재로서 애플리케이션과 분리되어 존재하게 된다.
이렇게 구성된 모듈을 다른 모듈이나 애플리케이션에 의해 재사용해야 한다.
import와 export를 통해 애플리케이션 내 코드의 단위를 명확히 분리할 수 있고, 재사용성이 좋아지기에 개발 효율성과 유지보수성을 높일 수 있다.
자바스크립트는 C언어처럼 모듈을 사용하기 위한 파일 스코프 및 import, export를 지원하지 않는다.
모듈처럼 사용하기 위해 자바스크립트 파일을 script 태그로 로드해도, 하나의 자바스크립트 파일 내에 있는 것처럼 작동하기 때문에 변수 중복 등의 문제가 발생할 수 있다.
이를 극복하기 위해 제안된 대책으로 CommonJS와 AMD(Asynchronous Module Definition)이 있다. 자바스크립트에서 모듈을 사용하기 위해는 이들을 구현한 모듈 로더 라이브러리를 사용해야 했다.
현재의 Node.js 런타임 환경에서는 CommonJS가 채택되었고, 모듈 시스템을 지원하기 때문에 파일별로 독립적인 파일 스코프(모듈 스코프)를 갖게 되었다.
ES6부터는 클라이언트 자바스크립트에서도 동작하는 모듈 기능이 추가되었다.
ESM의 사용법은 다음과 같다.
<script type="module" src="app.mjs"></script>
type="module" 속성을 통해 로드된 js 파일은 모듈로 동작한다.
ESM임을 명시하기 위해 .mjs 파일 확장자 사용을 권장한다.
ESM은 독자적인 모듈 스코프를 갖는다.
ESM이 아닌 기존의 js 파일은 여러 파일을 로드해도 하나의 js 파일처럼 동작하기에 독자적인 모듈 스코프를 갖지 않는다. (변수 중복, 재할당 등의 문제 발생)
ESM은 파일 자체의 독자적인 모듈 스코프를 제공하기에, ESM 내에서 선언한 변수는 전역 변수가 아니며 window 객체의 프로퍼티도 아니게 된다.
모듈 내부에서 선언한 식별자를 외부에 공개하여 다른 모듈들이 재사용할 수 있도록 하려면 export 키워드를 사용한다.
export 방법은 다음과 같이 두 가지 방법이 있다.
export const pi = Math.PI;
export function square(x) {
return x * x;
}
export class Person {
/* ... */
}
const pi = Math.PI;
function square(x) {
return x * x;
}
class Person {
/* ... */
}
export { pi, square, Person };
다른 모듈에서 export한 식별자를 로드하기 위해 import 키워드를 사용한다.
💡 ESM 파일은 파일 확장자를 생략할 수 없다.
import { pi, square, Person } from './lib.mjs';
console.log(pi, square(10), new Person('miseon'));
<script type="module" src="app.mjs"></script>
app.mjs는 애플리케이션의 진입점이므로, import문에 의해 로드되는 의존성이 존재하기에 반드시 script 태그로 로드해야 하지만, lib.mjs는 그렇지 않다.
import * as lib from './lib.mjs';
console.log(lib.pi);
// lib.mjs
export default x => x * x;
// app.mjs
import square from './lib.mjs';