본문 바로가기
architecture_spa

ESModules 심화1: 동적 import(), 번들러 처리 방식, tsconfig 설정 가이드

by 죄니안죄니 2025. 4. 26.

들어가며

JavaScript의 모듈 시스템이 ESModules(ESM)으로 표준화되면서 import/export는 이제 일상이 되었습니다.
특히 import()를 통한 동적 모듈 로딩, Vite/Webpack 같은 번들러의 ESM 처리 방식,
TypeScript에서의 tsconfig.json 설정까지 함께 이해하면 현대적 프로젝트 구조를 설계하는 데 큰 도움이 됩니다.

이 글에서는 다음 내용을 단계적으로 정리합니다:

  • import()로 코드 분할 및 동적 로딩
  • Vite/Webpack의 ESM 처리 방식 차이
  • TypeScript에서 module 설정과 사용법
  • React/Vue 컴포넌트 레벨 코드 스플리팅까지 실전 예시 포함
 

1. 동적 import(import())

button.addEventListener("click", async () => {
  const module = await import("./modal.js");
  module.openModal();
});
  • 정적 import와 달리 런타임에 모듈을 비동기로 로드
  • 반환값은 Promise → await 또는 .then()으로 처리 가능
  • 코드 스플리팅(Code Splitting)에 활용 → 초기에 필요 없는 모듈을 나중에 로드

📌 주의점

  • 브라우저 ESM 환경 또는 번들러(Vite/Webpack 등) 환경에서만 사용 가능
  • import 경로는 정적이어야 함 (template literal은 안됨)
 

2. Vite vs Webpack의 ESM 처리 방식

항목
Vite Webpack
개발 모드 Native ESM (브라우저 import 사용) 번들링 후 serve
빌드 방식 Rollup 기반 번들링 자체 번들러 (webpack/runtime)
코드 분할 import()로 자동 분리 import() → chunk 생성

✅ Vite

  • 개발 서버에서는 ESM 기반으로 import() 처리됨 (별도 번들 없이)
  • 빌드시에는 Rollup이 import()된 모듈을 chunk로 나눔

✅ Webpack

  • import()를 만나면 내부적으로 코드 스플리팅 수행
  • import() 위치 기준으로 별도 번들 생성 (e.g. 0.js)
 

3. TypeScript에서의 module 설정

tsconfig.json

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "esModuleInterop": true,
    "strict": true,
    "outDir": "dist"
  }
}
항목 설명
target 최신 JS 기능 사용 (예: dynamic import)
module ESModules 또는 ESNext로 설정
moduleResolution ESM 지원 위해 bundler 또는 node
esModuleInterop commonjs 모듈 호환 지원

import() 사용 예시

async function loadPage() {
  const { default: Page } = await import("./pages/Home.ts");
  Page.render();
}
  • TypeScript에서도 import()는 Promise를 반환
  • default 속성으로 가져옴 (export default 기준)
 

4. 실전 팁 및 컴포넌트 레벨 코드 스플리팅

✅ 조건부 import

if (isMobile()) {
  import("./mobile-only.js").then(...);
}

✅ Vite + Vue에서 레이지 로딩

const Page = defineAsyncComponent(() => import("./views/Page.vue"));

✅ React에서 lazy + Suspense

import React, { lazy, Suspense } from "react";

const Chart = lazy(() => import("./components/Chart"));

export default function Dashboard() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <Chart />
    </Suspense>
  );
}

 

✅ Webpack에서 chunk name 지정

import(/* webpackChunkName: "modal" */ "./components/Modal");
 

마치며

import()성능 최적화와 사용자 경험 개선의 핵심 도구이며,
ESModules 기반 번들러와 TypeScript 환경에서도 자연스럽게 활용할 수 있습니다.

    • Vite는 개발 단계에서 브라우저 ESM을 직접 사용해 빠른 반응성을 제공
    • Webpack은 안정적인 코드 스플리팅과 호환성을 보장
    • TypeScript의 module, moduleResolution, target 옵션은 런타임 구조와 연결된 중요한 설정입니다.
    • React/Vue에서는 컴포넌트 단위의 동적 import로 라우트 레벨 스플리팅 및 초기 로딩 개선 가능

📂 다음 글에서는:

  • Vite의 preload, prefetch 전략
  • Webpack에서 lazy chunk 오류 대응
  • React/Vue 컴포넌트 수준 코드 스플리팅

등을 이어서 다루겠습니다.

바로보기>>> ESModules심화2

 

댓글