← JavaScript 강의 목록으로
🧩
브라우저 API
심화 · 선수: 22_저장소

23. 모듈 (ESM)

한 파일에 모든 코드를 넣으면 충돌과 유지보수가 어렵습니다. 모듈은 파일별로 스코프를 격리하고 필요한 것만 노출합니다.

ES Modulesimportexport재사용
소요 시간
약 1시간
난이도
📊 중급
선수 조건
🎯 단원 22
결과물
한 파일에 모든 코드를 넣으면 충돌과 유지보수가 어렵습니다. 모듈은 파일별로 스코프를 격리하고 필요한 것만 노출합니다.

이 강의에서 배우는 것

  • 1ES Modules의 `import`/`export`를 사용할 수 있다.
  • 2named export와 default export를 구분한다.
  • 3`<script type="module">`로 브라우저에서 모듈을 로드한다.
  • 4re-export로 모듈을 묶어 제공한다.

소개

한 파일에 모든 코드를 넣으면 충돌과 유지보수가 어렵습니다. 모듈은 파일별로 스코프를 격리하고 필요한 것만 노출합니다.

핵심 개념

1. 왜 모듈인가

한 파일에 모든 코드를 넣으면 충돌과 유지보수가 어렵습니다. 모듈은 파일별로 스코프를 격리하고 필요한 것만 노출합니다.

2. export — named / default

javascript
// math.mjs
export const PI = 3.14159;
export function add(a, b) { return a + b; }

export default function multiply(a, b) { return a * b; }

named export는 이름 그대로, default는 한 모듈당 1개만 가능합니다.

3. import

javascript
import multiply, { PI, add } from './math.mjs';
import * as math from './math.mjs';
import { add as plus } from './math.mjs';

default는 중괄호 없이, named는 중괄호 안에 적습니다.

4. 브라우저에서 사용

html
<script type="module" src="./02_import.mjs"></script>

`type="module"`이 있어야 import 구문이 동작합니다. 모듈은 자동으로 `defer`되며 strict mode입니다.

5. re-export

한 진입점에서 여러 모듈을 묶어 제공할 때.

javascript
// index.mjs
export { add, PI } from './math.mjs';
export { format } from './format.mjs';

핵심 예제

파일다루는 내용
01_export.mjsnamed & default export
02_import.mjs01에서 import
03_named_default.mjs두 방식 혼합
04_reexport.mjsre-export 패턴
index.html`<script type="module">`

`index.html`을 로컬 서버로 열어야 합니다 (`file://`은 CORS 문제).

src/01_export.mjs

mjs
/**
 * named export와 default export 예시
 */
export const PI = 3.14159;

/**
 * 두 수의 합
 */
export function add(a, b) {
  return a + b;
}

/**
 * 두 수의 곱 (default)
 */
export default function multiply(a, b) {
  return a * b;
}

src/02_import.mjs

mjs
/**
 * 01_export.mjs에서 가져와 사용
 */
import multiply, { PI, add } from './01_export.mjs';

console.log('PI:', PI);
console.log('1+2 =', add(1, 2));
console.log('3*4 =', multiply(3, 4));

src/03_named_default.mjs

mjs
/**
 * named와 default를 함께 import / 별칭(alias) 사용
 */
import multiply, { add as plus, PI } from './01_export.mjs';
import * as math from './01_export.mjs';

console.log(plus(10, 20));
console.log(multiply(2, PI));
console.log('네임스페이스 사용:', math.add(5, 7));

src/04_reexport.mjs

mjs
/**
 * re-export — 다른 모듈을 묶어서 다시 내보내기
 * 외부에서는 이 파일 하나만 import 하면 됨
 */
export { add, PI } from './01_export.mjs';
export { default as multiply } from './01_export.mjs';

src/index.html

html
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <title>ESM 데모</title>
  </head>
  <body>
    <h1>ESM 데모</h1>
    <p>콘솔을 확인하세요.</p>
    <script type="module" src="./02_import.mjs"></script>
  </body>
</html>

자주 하는 실수

  1. `type="module"` 빼먹어서 `import`가 SyntaxError.
  2. default를 중괄호 `{ }`로 import.
  3. 상대경로에 `./` 누락 → 베어 모듈로 오인.
  4. 확장자 `.mjs`/`.js` 누락 (브라우저는 명시 필요).
  5. `file://`로 직접 열기 — 로컬 서버를 사용.

FAQ

Q1. `.js`와 `.mjs` 차이?

Node에서 `.mjs`는 ESM, `.js`는 package.json의 `type`에 따름. 브라우저는 `type="module"`만 보면 둘 다 OK. **Q2. CommonJS와 섞어 쓸 수 있나요?** A. Node에서 제한적으로 가능합니다. 24편에서 다룹니다. **Q3. 동적 import도 있나요?** A. `await import('./x.mjs')`로 런타임 로드 가능합니다.

과제

유틸 모듈을 만들어 HTML 페이지에서 사용하세요.

homework/README.md

## 과제 1 `utils.mjs`에 `formatPrice(n)` (예: 1000 → "1,000원"), `discount(price, percent)` 두 함수를 named export로 만들고, `main.mjs`에서 import 해 HTML 페이지에 출력하세요.

homework/answer/homework_01.html

html
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <title>유틸 모듈 데모</title>
  </head>
  <body>
    <h1>가격 계산</h1>
    <div id="out"></div>
    <script type="module" src="./homework_01_main.mjs"></script>
  </body>
</html>

homework/answer/homework_01_main.mjs

mjs
/**
 * utils 모듈을 사용해 화면에 표시
 */
import { formatPrice, discount } from './homework_01_utils.mjs';

const price = 25000;
const sale = discount(price, 20);

const out = document.getElementById('out');
out.innerHTML = `
  <p>정가: ${formatPrice(price)}</p>
  <p>할인가(20%): ${formatPrice(sale)}</p>
`;

homework/answer/homework_01_utils.mjs

mjs
/**
 * 가격을 천단위 콤마와 '원'으로 포맷
 */
export function formatPrice(n) {
  return `${n.toLocaleString('ko-KR')}원`;
}

/**
 * 할인가 계산
 */
export function discount(price, percent) {
  return Math.floor(price * (1 - percent / 100));
}

다음 단원

[24_Node_환경](../../07_Node_입문/24_Node_환경/)

예제 코드 / 강의 자료

전체 강의 자료와 예제 코드는 GitHub에서 자유롭게 받아볼 수 있습니다.

GitHub에서 보기 ↗