오늘날의 웹 개발은 복잡하고 방대해졌습니다. 단일 애플리케이션으로 모든 기능을 구현하려다 보면 관리와 유지보수가 어려워집니다. 이에 대한 해결책으로 등장한 것이 마이크로 프론트엔드입니다. 마이크로 프론트엔드는 각각의 기능을 독립적인 애플리케이션으로 나누어 개발하고, 이를 하나로 통합하여 관리하는 방법론입니다. 이번 글에서는 Next.js와 Module Federation을 사용하여 마이크로 프론트엔드를 구현하는 방법에 대해 알아보겠습니다.
Module Federation이란?
Module Federation은 Webpack 5에서 도입된 기능으로, 서로 다른 애플리케이션 간에 모듈을 공유하고 불러올 수 있게 해줍니다. 이를 통해 대규모 애플리케이션을 여러 개의 독립적인 마이크로 프론트엔드로 분할하여 개발하고 배포할 수 있습니다. 각 마이크로 프론트엔드는 자신의 번들을 유지하면서 필요한 모듈을 동적으로 로드하여 사용합니다.
Next.js와 Module Federation의 결합
Next.js는 React 기반의 프레임워크로, 서버사이드 렌더링(SSR)과 정적 사이트 생성(SSG)을 지원합니다. 이러한 Next.js에 Module Federation을 결합하면, Next.js 애플리케이션을 여러 개의 마이크로 프론트엔드로 나누어 관리할 수 있습니다. 이를 가능하게 해주는 것이 바로 NextFederationPlugin입니다.
NextFederationPlugin 설정 방법
먼저, NextFederationPlugin을 설치합니다.
npm install @module-federation/nextjs-mf
다음으로, `next.config.js` 파일을 수정하여 플러그인을 설정합니다.
const NextFederationPlugin = require('@module-federation/nextjs-mf');
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(
new NextFederationPlugin({
name: 'container', // 호스트 애플리케이션 이름
filename: 'static/chunks/remoteEntry.js',
remotes: {
flight: 'flight@http://localhost:3001/_next/static/remoteEntry.js',
hotel: 'hotel@http://localhost:3002/_next/static/remoteEntry.js',
},
exposes: {
'./NavBar': './components/NavBar', // 노출할 모듈
},
shared: {
react: {
singleton: true,
eager: true,
requiredVersion: false,
},
'react-dom': {
singleton: true,
eager: true,
requiredVersion: false,
},
},
})
);
}
return config;
},
};
위 설정에서 `name`은 호스트 애플리케이션의 이름을 지정하며, `remotes`는 외부 애플리케이션(마이크로 프론트엔드)의 엔트리 포인트를 지정합니다. `exposes`는 호스트 애플리케이션에서 노출할 모듈을 정의하고, `shared`는 공통으로 사용할 라이브러리를 설정합니다.
원격 애플리케이션 설정
각 원격 애플리케이션도 마찬가지로 설정이 필요합니다. 예를 들어, `flight` 애플리케이션의 `next.config.js` 파일을 다음과 같이 설정합니다.
const NextFederationPlugin = require('@module-federation/nextjs-mf');
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.plugins.push(
new NextFederationPlugin({
name: 'flight', // remote 애플리케이션 이름
filename: 'static/remoteEntry.js',
exposes: {
'./FlightDetails': './components/FlightDetails', // 노출할 모듈
},
shared: {
react: {
singleton: true,
eager: true,
requiredVersion: false,
},
'react-dom': {
singleton: true,
eager: true,
requiredVersion: false,
},
},
})
);
}
return config;
},
};
모듈 사용 예시
호스트 애플리케이션에서 원격 모듈을 사용하는 방법은 다음과 같습니다.
import dynamic from 'next/dynamic';
const FlightDetails = dynamic(() => import('flight/FlightDetails'), { ssr: false });
export default function HomePage() {
return (
<div>
<h1>Home Page</h1>
<FlightDetails />
</div>
);
}
위 예제에서는 `dynamic`을 사용하여 `flight` 애플리케이션의 `FlightDetails` 모듈을 동적으로 로드하고 있습니다. 이는 Next.js의 동적 임포트를 활용한 방식으로, 서버사이드 렌더링 시 모듈 로딩을 지연시킬 수 있습니다.
결론
Next.js와 Module Federation을 사용하면 대규모 애플리케이션을 여러 개의 마이크로 프론트엔드로 나누어 효율적으로 관리할 수 있습니다. 각 마이크로 프론트엔드는 독립적으로 개발 및 배포될 수 있으며, 필요한 모듈을 동적으로 로드하여 사용할 수 있습니다. 이러한 아키텍처는 개발 속도를 높이고, 팀 간의 의존성을 줄이며, 유지보수를 쉽게 만들어줍니다.
NextFederationPlugin을 통해 Next.js 애플리케이션에서 Module Federation을 쉽게 구현할 수 있으며, 이를 통해 현대적인 웹 개발의 복잡성을 효과적으로 관리할 수 있습니다. 여러분도 Next.js와 Module Federation을 사용하여 마이크로 프론트엔드를 구현해 보세요. 이를 통해 더욱 유연하고 확장 가능한 애플리케이션을 만들 수 있을 것입니다.