본 글에서는 ESM(ECMA Script Module)에 대해서 알아보겠습니다.
자바스크립트는 ECMA Script Module System을 제공합니다.
자바스크립트에서 모듈은 컴포넌트와 로직을 분리하고 관리하기 위한 기본 단위입니다.
모듈은 클래스 하나 또는 특정한 목적을 가진 여러 함수로 구성된 라이브러리처럼 사용할 수 있습니다.
모듈 내부의 변수나 함수를 외부에서 사용할 수 있도록 하려면 모듈 내부에 특수한 지시자, export 를 사용해 공개해야 합니다.
마찬가지로 특수한 지시자,import 를 통해 공개된 외부 모듈을 가져와 사용할 수 있습니다.
⚠️ 모듈은 로컬 파일에서 동작하지 않고, HTTP, HTTPS 프로토콜을 통해서만 동작합니다.
브라우저 환경에서 ES 모듈을 사용하려면 로컬 파일 시스템(file://)이 아닌, HTTP 또는 HTTPS 환경에서 로드해야 정상 동작합니다.
모듈은 항상 use strict로 실행됩니다.
참고 - [MDN] Strict mode - JavaScript
// index.mjs
let name = 'Yuna'
console.log(name) // 출력: Yuna
// test.mjs
let name = 'Jo'
console.log(name) // 출력: Jo
<!-- html -->
<script type='module' src='src/index.mjs'></script>
<script type='module' src='src/test.mjs'></script>
일반 자바스크립트 파일은 모두 전역 스코프를 공유합니다. 이로 인해 서로 다른 파일에서 동일한 이름의 식별자를 선언하면 충돌이나 의도치 않은 동작이 발생할 수 있습니다.
type="module" 속성을 사용하면 각 스크립트는 자체적인 모듈 스코프를 가지게 되어, 변수나 함수가 전역을 오염시키지 않습니다.
모듈 파일은 보통
.mjs확장자를 사용하지만,.js확장자도 함께 사용할 수 있습니다.
예시1
// 📁 alert.js alert("모듈이 평가되었습니다!"); // 동일한 모듈을 여러 모듈에서 가져오기 // 📁 1.js import './alert.js'; // 얼럿창에 '모듈이 평가되었습니다!'가 출력됩니다. // 📁 2.js import './alert.js'; // 아무 일도 발생하지 않습니다.
예시2
// 📁 admin.js export let admin = { name: "John" }; // 📁 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 객체가 전달됩니다.
- 각 모듈에 동일한 admin 객체가 전달되는 것입니다.
📕 요약
- 모듈은 단 한 번만 실행됨
- 실행된 결과는 모든 import 대상에 공유됨
- 한 모듈에서 객체 및 데이터를 수정하면, 이를 가져다 쓰는 다른 모듈에서도 변경 사항이 반영됨
💡 부연 설명
ESM(ECMAScript Module)은 모듈을 싱글턴(singleton) 처럼 다룹니다.
즉, 한 번 로드된 모듈은 캐시에 저장되고, 이후import할 때마다 동일한 인스턴스가 반환됩니다.
import.meta 객체는 현재 모듈에 대한 정보를 제공합니다.
호스트 환경에 따라 제공하는 정보의 내용은 다르나, 브라우저 환경에선 스크립트의 URL 정보를 얻을 수 있습니다.
HTML 안에 있는 모듈이라면, 현재 실행 중인 웹페이지의 URL 정보를 얻을 수 있습니다.
<script type="module">
alert(import.meta.url); // script URL (인라인 스크립트가 위치해 있는 html 페이지의 URL)
</script>
모듈의 최상위에서 this는 undefined입니다.
반면, 일반 스크립트에서는 this가 전역 객체(window)를 가리킵니다.
이처럼 동일한 코드라도 실행 환경(모듈 vs 일반 스크립트)에 따라 this의 값이 달라집니다.
<script>
alert(this); // window
</script>
<script type="module">
alert(this); // undefined
</script>
자바스크립트를 마스터하기 전에 React를 먼저 쓰다보니(React도 잘 모릅니다..) 자바스크립트에서 어떻게 모듈을 만들고 활용하는지, 그 시스템은 어떤지에 대해서 몰랐습니다. 모듈이라는 개념 자체가 없다고 생각했었거든요.!
React에서는 모듈을 만들어보고 사용해봐서 느낌은 알지만, 자바스크립트처럼 ESM 시스템을 그대로 활용하는지 알아봐야겠습니다.