19강

모듈과 import/export

4 조회 1

ES 모듈 시스템의 named export와 default export를 구분하고, import 다양한 문법을 익힌다. CommonJS와의 차이, 동적 import, 번들러의 역할을 이해한다.

모듈 — 코드를 파일 단위로 나누기

모듈(Module)은 코드를 논리적 단위로 분리하는 시스템입니다. 모든 변수와 함수를 하나의 파일에 쓰면 충돌, 유지보수 어려움이 생깁니다. 모듈을 사용하면 파일별로 독립된 스코프를 가지고, 필요한 것만 외부에 공개할 수 있습니다.

자바스크립트는 두 가지 모듈 시스템이 공존합니다: CommonJS(CJS)ES Module(ESM).

ES 모듈 기본 — export와 import

// utils/math.js
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }
export const PI = 3.14159;

// utils/string.js
export function capitalize(str) {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

// main.js
import { add, PI } from "./utils/math.js";
import { capitalize } from "./utils/string.js";

console.log(add(2, 3)); // 5
console.log(PI);        // 3.14159

Named Export vs Default Export

// Named Export — 여러 개 내보내기 가능
export const name = "Kim";
export function greet() { ... }
export class User { ... }

// 한번에 묶어서 내보내기
function add(a, b) { return a + b; }
function subtract(a, b) { return a - b; }
export { add, subtract };

// 별칭으로 내보내기
export { add as sum, subtract as minus };

// Default Export — 파일당 하나만 가능
export default function fetchUser(id) {
  return fetch(`/api/users/${id}`).then(r => r.json());
}

// 또는
function fetchUser(id) { ... }
export default fetchUser;

다양한 import 문법

// Named import
import { add, subtract } from "./math.js";

// 별칭으로 import
import { add as sum, subtract as minus } from "./math.js";

// 전체를 네임스페이스로 import
import * as MathUtils from "./math.js";
MathUtils.add(2, 3);   // 5
MathUtils.PI;          // 3.14159

// Default import (이름은 자유롭게)
import fetchUser from "./api.js";
import getUser from "./api.js"; // 같은 것, 이름만 다름

// Named + Default 동시 import
import fetchUser, { BASE_URL, handleError } from "./api.js";

// 사이드 이펙트만 실행 (반환값 없음)
import "./polyfills.js";
import "./global-styles.css";

재내보내기 (Re-export) — 배럴 파일 패턴

// utils/index.js — 하위 모듈들을 한 곳에서 내보내기
export { add, subtract, PI } from "./math.js";
export { capitalize, truncate } from "./string.js";
export { formatDate, parseDate } from "./date.js";
export { default as fetchUser } from "./api.js";

// 사용하는 쪽
import { add, capitalize, formatDate, fetchUser } from "./utils";
// 내부 구조 알 필요 없이 utils에서 모두 가져옴

CommonJS — Node.js의 전통 방식

// CommonJS (Node.js, .cjs 파일)
const fs = require("fs");
const { join } = require("path");

module.exports = {
  add: (a, b) => a + b,
  PI: 3.14159
};

// 또는
module.exports = function fetchUser(id) { ... };

// ESM과 CJS 주요 차이
// CJS: 동기적, require는 어디서나 호출 가능
// ESM: 정적 분석 가능, 트리 쉐이킹 최적화
// ESM: 비동기 로딩 지원, import는 최상위에서만

동적 import — 코드 분할

// 정적 import는 항상 파일 상단에 위치
// 동적 import는 조건부, 지연 로딩 가능

// 버튼 클릭 시에만 무거운 모듈 로드
button.addEventListener("click", async () => {
  const { default: Chart } = await import("./chart.js");
  const chart = new Chart(container, data);
});

// 조건부 로드
async function loadLocale(lang) {
  const messages = await import(`./locales/${lang}.js`);
  return messages.default;
}

// 여러 모듈 동적 로드
const [moduleA, moduleB] = await Promise.all([
  import("./moduleA.js"),
  import("./moduleB.js")
]);

번들러 — Vite, Webpack, esbuild

브라우저는 아직 모든 ESM 기능(경로 별칭, npm 패키지 직접 import 등)을 완벽히 지원하지 않습니다. 번들러는 여러 모듈 파일을 하나(또는 몇 개)의 파일로 합쳐줍니다.

번들러의 역할:
1. import/export 분석 → 의존성 그래프 구성
2. 여러 파일을 하나로 합치기 (번들링)
3. 사용하지 않는 코드 제거 (트리 쉐이킹)
4. TypeScript, JSX, CSS 변환 (트랜스파일링)
5. 코드 최소화 (미니피케이션)
6. 개발 서버 + HMR(핫 모듈 교체)

주요 번들러:
- Vite (현재 가장 빠름, Rollup 기반)
- Webpack (가장 오래됨, 설정 복잡)
- esbuild (Go 기반, 초고속)
- Parcel (설정 없이 사용)

package.json "type" 필드

{
  "type": "module"  // .js 파일을 ESM으로 처리
}
// "type": "commonjs" (기본값) — .js 파일을 CJS로 처리

// 개별 파일 강제:
// .mjs → 항상 ESM
// .cjs → 항상 CJS

모듈 설계 원칙

// 1. 단일 책임: 한 모듈은 하나의 역할
// auth.js — 인증 관련만
// api.js  — API 호출만
// utils.js — 유틸리티 함수들

// 2. 명확한 공개 API
// 내부에서만 쓰는 것은 export 하지 않음

// 3. 순환 의존성 주의
// a.js → b.js → a.js (순환)는 예상치 못한 버그 유발

// 4. index.js 배럴 파일로 폴더 단위 캡슐화
// components/Button/Button.jsx
// components/Button/index.js  → export { default } from "./Button"
// import Button from "./components/Button" (내부 구조 숨김)

관련 검색어  ·  자바스크립트 모듈, import export 문법, named vs default export, 동적 import, CommonJS ESM 차이, 번들러란

채용정보
공지사항
인사이트
MY