-
🧩 Rspack 기반 Module Federation 튜토리얼 (React 기반 MFA)React 2025. 6. 19. 22:23
🎯 들어가며
React로 Micro-Frontend architecture(MFA)를 구성할 때 Webpack 기반의 Module Federation은 꽤 강력한 옵션이다.
그런데 최근 등장한 Rspack은 Webpack과 API가 유사하면서도 훨씬 빠른 빌드 성능을 자랑한다.
이번 글에서는 Rspack 환경에서 Module Federation과 Hot Module Replacement(HMR) 를 적용하여 MFE 구조를 만드는 방법을 간단하게 기록해봤다.- Rspack으로 Module Federation 구성하기
- React 앱 간 모듈 공유 (Remote ↔ Host)
- HMR이 잘 적용되는 구조로 설정하기
공식 문서와 module-federation-examples/rspack_hmr 예제를 바탕으로 예제를 만들었다.
📁 프로젝트 구조 미리보기
rspack-mf-hmr/ ├── host/ # Module을 소비하는 앱 │ ├── src/ │ │ ├── App.tsx │ │ ├── bootstrap.tsx 👈 React 마운트 분리 │ │ └── index.tsx 👈 bootstrap 로드 전용 │ └── rspack.config.js ├── remote/ # Module을 제공하는 앱 │ ├── src/ │ │ ├── Button.tsx │ │ └── index.ts │ └── rspack.config.js⚙️ 1. 기본 설정
먼저 Host/Remote 각각의 앱을 셋업한다.
# 루트 디렉토리 생성 mkdir rspack-mf-hmr && cd rspack-mf-hmr # Host 앱 초기화 mkdir host && cd host npm init -y npm install react react-dom npm install --save-dev @rspack/core @rspack/cli swc-loader html-webpack-plugin # Remote 앱 초기화 cd .. mkdir remote && cd remote npm init -y npm install react react-dom npm install --save-dev @rspack/core @rspack/cli swc-loader🧱 2. Remote 앱 구성 (버튼 제공)
remote/src/Button.tsx
import React from "react"; const Button = () => { return <button style={{ padding: 10 }}>Remote Button</button>; }; export default Button;👆 아주 단순한 버튼 컴포넌트다. 이걸 외부에서 소비할 수 있도록 만들어보자.
remote/src/index.ts
export { default as Button } from "./Button";👆 기본적으로 외부에서 import("remote/Button")으로 접근할 수 있도록 index에서 export 해주자.
remote/rspack.config.js
const path = require("path"); const { ModuleFederationPlugin } = require("@rspack/core").container; module.exports = { entry: "./src/index.ts", output: { path: path.resolve(__dirname, "dist"), filename: "bundle.js", publicPath: "http://localhost:3001/", uniqueName: "remote", }, mode: "development", devServer: { port: 3001, hot: true, }, plugins: [ new ModuleFederationPlugin({ name: "remote", filename: "remoteEntry.js", exposes: { "./Button": "./src/Button.tsx", }, shared: { react: { singleton: true }, "react-dom": { singleton: true }, }, }), ], resolve: { extensions: [".tsx", ".ts", ".js"] }, module: { rules: [ { test: /\.tsx?$/, use: "swc-loader", }, ], }, };📌 React와 ReactDOM은 싱글톤으로 공유해야 충돌 없이 동작한다.
🏠 3. Host 앱 구성 (버튼 소비)
host/public/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Host App</title> </head> <body> <div id="root"></div> </body> </html>host/src/App.tsx
import React from "react"; const RemoteButton = React.lazy(() => import("remote/Button")); const App = () => ( <React.Suspense fallback="Loading..."> <h1>Host App</h1> <RemoteButton /> </React.Suspense> ); export default App;👆 Remote에서 Button 컴포넌트를 lazy load하고, suspense로 fallback UI까지 지정해주자.
host/src/bootstrap.tsx
import React from "react"; import { createRoot } from "react-dom/client"; import App from "./App"; const root = createRoot(document.getElementById("root")!); root.render(<App />);👆 React 18 이상에서의 마운팅 방식이다. Module Federation과 혼용 시 충돌 방지를 위해 분리한다.
host/src/index.tsx
// React 18 + Module Federation 호환을 위한 분리된 부트스트랩 import("./bootstrap");👆 bootstrap.tsx를 dynamic import하면, 모듈 페더레이션의 런타임과 React의 마운트 순서를 조정할 수 있다.
host/rspack.config.js
const path = require("path"); const { ModuleFederationPlugin } = require("@rspack/core").container; const HtmlWebpackPlugin = require("html-webpack-plugin"); module.exports = { entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "dist"), filename: "bundle.js", publicPath: "http://localhost:3000/", uniqueName: "host", }, mode: "development", devServer: { port: 3000, hot: true, }, plugins: [ new ModuleFederationPlugin({ name: "host", remotes: { remote: "remote@http://localhost:3001/remoteEntry.js", }, shared: { react: { singleton: true }, "react-dom": { singleton: true }, }, }), new HtmlWebpackPlugin({ template: "./public/index.html" }), ], resolve: { extensions: [".tsx", ".ts", ".js"] }, module: { rules: [ { test: /\.tsx?$/, use: "swc-loader", }, ], }, };🚀 실행 & 확인하기
# Remote 앱 실행 cd remote npx rspack dev # Host 앱 실행 cd ../host npx rspack dev- 브라우저에서 Host 앱 접속 → http://localhost:3000
- 버튼이 잘 나타나는지 확인
✅ HMR 동작 확인
remote/src/Button.tsx 파일을 수정한 뒤 저장하면, Host 앱에서도 자동으로 반영되는지 확인해보자.
🤔 bootstrap.tsx 분리 이유는?
HMR 충돌 방지 Module Federation이 React 마운트를 제어하는 경우 충돌 우려 → 분리 필수 React 18 지원 createRoot()는 DOM 준비 이후에 실행되어야 안전 테스트 용이 마운트와 로직을 분리하면 유닛 테스트 등에서 유리 이 패턴은 Webpack/Rspack 환경에서 Module Federation + React 18을 함께 쓸 때 거의 필수다.
📚 참고 자료
✨ 마무리하며
Rspack은 빠른 속도와 Webpack 호환성을 모두 잡은 빌드 도구다.
여기에 Module Federation까지 접목하면 확장성 높은 MFE 아키텍처를 구현할 수 있다.
이번 글을 통해 Remote ↔ Host 앱 간 컴포넌트 공유와 HMR 연동까지 알아보았고, 다음 단계로는 SSR이나 동적 Remote 로딩, 다중 Remote 연결 같은 추가 기능을 설정해봐야 한다.✅ 왜 Rspack에서 MFE를 시도했는가?
- Webpack보다 훨씬 빠른 빌드 시간 → 개발 경험 개선
- MFE + HMR을 자연스럽게 적용할 수 있는 환경 제공
✅ 기존 Webpack 대비 성능 차이?
- Rspack은 Rust로 작성되어 빌드/번들링 속도가 Webpack보다 최대 10배 빠릅니다 (특히 HMR 적용 시 체감 큼)
✅ 실무에서 어떻게 활용 가능할까?
- 사일로 팀 구조에서 앱을 나누어 독립 배포하고 싶을 때
- 다양한 FE 앱이 공통 UI 컴포넌트를 공유할 때
- 디자인 시스템을 별도 Remote 앱으로 운영하고 싶을 때
도움이 되셨다면 ⭐️, 댓글로 궁금한 점을 남겨주세요!
🍋 실제 작성한 예제 코드
https://github.com/citron03/practice-rspack-1/commit/237d2a0f8c79824f7877e0ef5bdc75aa36a7c60c
feat: example rspack host & remote button · citron03/practice-rspack-1@237d2a0
1+# Dependency directories
github.com
'React' 카테고리의 다른 글
React에서 우클릭 메뉴를 커스텀하게 만들기 (onContextMenu 이벤트를 활용한 간단한 메뉴 구현) 😘 (3) 2025.07.27 Controlled 컴포넌트와 UnControlled 컴포넌트 😊 공통 컴포넌트 고민해보기 (1) 2025.07.13 MDX 설정하기 in Next.js 15 🍝 (Markdown for thecomponent era) (0) 2025.05.18 React를 사용할 때, HTML을 직접 삽입하기 - dangerouslySetInnerHTML 사용 예제 (0) 2025.04.20 React에서 XState 간단 사용 후기 😊 (0) 2025.02.13