테마
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 # 노출할 컴포넌트실행 순서:
- Remote 앱(component-app)을 먼저 실행하여 remoteEntry.js를 제공
- Host 앱(main-app)을 실행하여 Remote의 모듈을 런타임에 로드
- 두 앱을 동시에 실행:
pnpm --parallel start:live
create-mf-appCLI를 사용하면 Module Federation 기본 설정이 포함된 프로젝트를 빠르게 생성할 수 있다.
핵심 정리
| 항목 | 내용 |
|---|---|
| Module Federation | Webpack 5 내장 플러그인으로, 런타임에 앱 간 코드 공유 |
| Host | 다른 앱의 모듈을 import하여 사용하는 소비자 앱 |
| Remote | exposes로 모듈을 노출하고 remoteEntry.js를 생성하는 제공자 앱 |
| Shared | React 등 공통 의존성을 중복 로드하지 않도록 공유하는 메커니즘 |
| remoteEntry.js | Remote 빌드 시 생성되는 진입점으로 모듈 메타데이터 포함 |
| import 경로 규칙 | 리모트이름/모듈경로 형식으로 Remote의 name + exposes 키를 조합 |
다음 단계
- Vite 모듈 페더레이션에서 Vite 환경의 Module Federation과 Webpack MF와의 차이점을 학습한다