Skip to content

Webpack 5 Module Federation Plugin 기초

Module Federation은 Webpack 5에 내장된 고급 모듈 통합 기능으로, 여러 독립 애플리케이션 간에 코드를 런타임에 동적으로 공유할 수 있게 해준다.

학습 목표

  • Module Federation의 개념과 마이크로프론트엔드에서의 역할을 이해한다
  • Host, Remote, Shared 세 가지 핵심 구성 요소를 구분하고 설명할 수 있다
  • remoteEntry.js의 역할과 생성 원리를 파악한다
  • webpack.config.js에서 ModuleFederationPlugin의 기본 설정 방법을 익힌다
  • 두 개의 React 앱 간에 컴포넌트를 런타임에 공유하는 흐름을 설계할 수 있다

1. Module Federation이란

Module Federation은 Webpack 5에서 소개된 고급 모듈 통합 기능이다. 여러 자바스크립트 애플리케이션 간에 코드를 동적으로 공유할 수 있게 해주며, 기존의 코드베이스를 변경할 필요 없이 Webpack이 모듈을 원격으로 로드하도록 처리한다.

Module Federation의 핵심 특징:

특징설명
런타임 통합빌드 타임이 아닌 런타임에 모듈을 동적으로 로드
독립 배포각 애플리케이션이 독자적인 빌드 파이프라인 보유
코드 변경 불필요import 구문만으로 다른 서버의 모듈 사용 가능
모든 JS 공유 가능UI 컴포넌트, 비즈니스 로직, 유틸리티 등 모든 유형
Webpack 내장별도 설치 없이 Webpack 5에 기본 포함

2. 핵심 구성 요소: Host, Remote, Shared

Module Federation은 세 가지 핵심 구성 요소로 이루어진다.

2.1 Host (호스트)

Host 애플리케이션은 다른 애플리케이션(Remote)으로부터 모듈을 로드하는 주체이다. 웹 애플리케이션의 메인 셸로, 사용자가 처음 접속하는 진입점 역할을 수행한다.

  • remotes 설정을 통해 어떤 리모트 앱에서 모듈을 가져올지 정의
  • import 구문을 사용하여 리모트 모듈을 코드에서 참조
  • 리모트 앱의 remoteEntry.js를 참조하여 모듈 메타데이터를 획득

2.2 Remote (리모트)

Remote 애플리케이션은 호스트에 로드될 수 있는 모듈을 제공하는 주체이다. 독립적으로 배포할 수 있는 별도의 코드베이스를 보유한다.

  • exposes 설정을 통해 외부에 노출할 모듈을 정의
  • 빌드 시 remoteEntry.js 파일을 자동 생성
  • 하나의 앱이 Host이면서 동시에 Remote 역할을 할 수도 있음

2.3 Shared (공유)

Shared 모듈은 여러 애플리케이션 간에 공유되는 의존성이다. React처럼 호스트와 리모트 양쪽에서 사용하는 라이브러리를 한 번만 로드하여 중복을 방지한다.

  • shared 설정을 통해 공유할 라이브러리 목록 정의
  • 중복 코드 로딩 방지로 번들 크기 절감
  • 버전 호환성에 따라 자동으로 공유 여부 결정

3. remoteEntry.js의 역할

Remote 애플리케이션은 빌드 과정에서 remoteEntry.js라는 특수한 진입점 파일을 생성한다. 이 파일은 Remote 애플리케이션의 인터페이스 역할을 하며, 노출된 모듈의 메타데이터와 주소를 모두 포함한다.

remoteEntry.js가 포함하는 정보:

  • 노출된 모듈(exposes)의 목록과 각 모듈의 청크 위치
  • 공유 모듈(shared)의 버전 정보와 호환성 데이터
  • Webpack 런타임 코드 (모듈 로딩 메커니즘)

Host 애플리케이션은 이 remoteEntry.js를 참조하여 필요한 모듈을 동적으로 로드한다. 이 요청은 개발자가 직접 수행하는 것이 아니라 Webpack의 런타임 코드에 의해 자동으로 처리된다.


4. 기본 webpack.config.js 설정

4.1 Remote 측 설정 (모듈을 노출하는 쪽)

js
// apps/component-app/webpack.config.js
const { ModuleFederationPlugin } = require("webpack").container;

module.exports = {
  // ... 기타 webpack 설정
  plugins: [
    new ModuleFederationPlugin({
      // 이 앱의 고유 이름 (Host에서 참조할 때 사용)
      name: "componentApp",

      // 빌드 시 생성될 진입점 파일 이름
      filename: "remoteEntry.js",

      // 외부에 노출할 모듈 정의
      exposes: {
        "./Button": "./src/components/Button",
      },

      // 앱 간 공유할 의존성
      shared: {
        react: { singleton: true, requiredVersion: "^18.0.0" },
        "react-dom": { singleton: true, requiredVersion: "^18.0.0" },
      },
    }),
  ],
};

4.2 Host 측 설정 (모듈을 사용하는 쪽)

js
// apps/main-app/webpack.config.js
const { ModuleFederationPlugin } = require("webpack").container;

module.exports = {
  // ... 기타 webpack 설정
  plugins: [
    new ModuleFederationPlugin({
      name: "mainApp",

      // 리모트 앱 등록
      // 형식: "스코프이름@리모트서버주소/remoteEntry.js"
      remotes: {
        componentApp:
          "componentApp@http://localhost:3001/remoteEntry.js",
      },

      shared: {
        react: { singleton: true, requiredVersion: "^18.0.0" },
        "react-dom": { singleton: true, requiredVersion: "^18.0.0" },
      },
    }),
  ],
};

4.3 설정 항목 간의 연결 관계

Host 설정연결 대상Remote 설정
remotes의 키 (componentApp)--- 이름 매칭 --->name (componentApp)
URL 경로의 파일명 (remoteEntry.js)--- 파일 매칭 --->filename (remoteEntry.js)
import 경로 (componentApp/Button)--- 모듈 매칭 --->exposes의 키 (./Button)

4.4 Host에서 리모트 모듈 사용

jsx
// apps/main-app/src/App.jsx
import React from "react";

// remotes 설정의 키 + exposes 설정의 키를 조합
import Button from "componentApp/Button";

function App() {
  return (
    <div>
      <h1>Main App</h1>
      <Button type="primary" onClick={() => console.log("클릭!")}>
        리모트 버튼
      </Button>
    </div>
  );
}

export default App;

import Button from "componentApp/Button" 구문에서:

  • componentApp은 Host의 remotes 설정 키와 매칭
  • /Button은 Remote의 exposes 설정에서 ./Button 키와 매칭
  • Webpack 런타임이 이 조합을 해석하여 Remote 서버에서 모듈을 동적 로드

5. 프로젝트 구조와 실행

Module Federation 기반 프로젝트는 일반적으로 모노레포 구조에서 각 앱을 독립 워크스페이스로 관리한다.

module-federation-example/
  pnpm-workspace.yaml        # 워크스페이스 정의
  package.json               # 루트 스크립트 (dev, build, serve)
  apps/
    main-app/                # Host (포트 3000)
      webpack.config.js      # remotes 설정
      src/
        App.jsx              # 리모트 컴포넌트 사용
    component-app/           # Remote (포트 3001)
      webpack.config.js      # exposes, filename 설정
      src/
        components/
          Button.jsx         # 노출할 컴포넌트

실행 순서:

  1. Remote 앱(component-app)을 먼저 실행하여 remoteEntry.js를 제공
  2. Host 앱(main-app)을 실행하여 Remote의 모듈을 런타임에 로드
  3. 두 앱을 동시에 실행: pnpm --parallel start:live

create-mf-app CLI를 사용하면 Module Federation 기본 설정이 포함된 프로젝트를 빠르게 생성할 수 있다.


핵심 정리

항목내용
Module FederationWebpack 5 내장 플러그인으로, 런타임에 앱 간 코드 공유
Host다른 앱의 모듈을 import하여 사용하는 소비자 앱
Remoteexposes로 모듈을 노출하고 remoteEntry.js를 생성하는 제공자 앱
SharedReact 등 공통 의존성을 중복 로드하지 않도록 공유하는 메커니즘
remoteEntry.jsRemote 빌드 시 생성되는 진입점으로 모듈 메타데이터 포함
import 경로 규칙리모트이름/모듈경로 형식으로 Remote의 name + exposes 키를 조합

다음 단계