자바스크립트가 만들어 진지 얼마 안 되었을 때는 자바스크립트로 만든 스크립트의 크기도 작고 기능도 단순했기 때문에 자바스크립트는 긴 세월 동안 모듈 관련 표준 문법 없이 성장할 수 있었습니다.
그런데 스크립트의 크기가 점차 커지고 기능도 복잡해지자 특별한 라이브러리를 만들어 필요한 모듈을 언제든지 불러올 수 있게 해준다거나 코드를 모듈 단위로 구성해 주는 방법을 만드는 등 다양한 시도를 하게됩니다.
모듈 시스템은 2015년에 표준으로 등재되었습니다. 이 이후로 관련 문법은 진화를 거듭해 이제는 대부분의 주요 브라우저와 Node.js가 모듈 시스템을 지원하고 있습니다.
모듈은 하나의 파일입니다. 즉, 스크립트 하나는 모듈 하나입니다.
모듈에 특수한 지시자 export 와 import 를 적용하면 다른 모듈을 불러와 불러온 모듈에 있는 함수를 호출하는 것과 같은 '기능 공유'가 가능합니다.
모듈은 특수한 키워드나 기능과 함께 사용되므로
<script type="module">
와 같은 속성을 설정해 해당 스크립트가 모듈이란 걸 브라우저가 알 수 있게 해줘야 합니다.
모듈은 항상 엄격 모드(use strict)로 실행되니다. 선언되지 않은 변수에 값을 할당하는 등의 코드는 에러를 발생시킵니다.
<script type="module">
a = 5; // 에러
</script>
모듈은 자신만의 스코프가 있습니다. 따라서 모듈 내부에서 정의한 변수나 함수는 다른 스크립트에서 접근할 수 없습니다.
외부에 공개하려는 모듈은 export 해야 하고, 내보내진 모듈을 가져와 사용하려면 import 해줘야 합니다.
// user.js
export let user = "Hailey";
// hello.js
import {user} from "./user.js";
document.body.innerHTML = user; // Hailey
// index.html
<!doctype html>
<script type="module" src="hello.js"></script>
동일한 모듈이 여러 곳에서 사용되더라도 모듈은 최초 호출 시 단 한 번만 실행됩니다. 실행 후 결과는 이 모듈을 가져가려는 모든 모듈에 내보내 집니다.
alert 함수가 있는 모듈(alert.js)을 여러 모듈에서 가져오기로 해보면, alert창은 단 한 번만 나타납니다.
// alert.js
alert("모듈이 평가되었습니다!");
// 동일한 모듈을 여러 모듈에서 가져오기
// 1.js
import `./alert.js`; // alert창에 '모듈이 평가되었습니다!'가 출력된다.
// 2.js
import `./alert.js`; // 아무 일도 발생하지 않는다.
실무에선 최상위 레벨 모듈을 대개 초기화나 내부에서 쓰이는 데이터 구조를 만들고 이를 내보내 재사용하고 싶을 때 사용합니다.
// admin.js
export let admin = {
name: "Hailey"
};
// 1.js
import {admin} from './admin.js';
admin.name = "Pete";
// 2.js
import {admin} from './admin.js';
alert(admin.name); // Pete
// 1.js와 2.js 모두 같은 객체를 가져오므로
// 1.js에서 객체에 가한 조작을 2.js에서도 확인할 수 있다.
admin 객체가 만들어지고 이 모듈을 가져오는 모든 모듈에 동일한 admin 객체가 전달됩니다.
즉, 모듈은 단 한 번만 실행되고 실행된 모듈은 필요한 곳에 공유되므로 어느 한 모듈에서 admin 객체를 수정하면 다른 모듈에서도 변경사항을 확인할 수 있습니다.