์ต๊ทผ ํ์ฌ์์ MFA๋ฅผ ํ์ฉํ ํ๋ก์ ํธ๋ฅผ ์งํํด ๋ณด์๋ ์ด์ผ๊ธฐ๊ฐ ์์ด ๊ณต๋ถ๋ฅผ ํ๊ณ ์์ต๋๋ค.
ํด๋น ๊ฐ๋
์ ์๊ฒ ๋ ์ง๋ ์ผ๋ง ๋์ง ์์๋๋ฐ, ์ฐ์ MFA๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ ์ค ํ๋์ธ Module Federation์ ๊ฐ๋จํ ์ฒดํํด ๋ณด์์ต๋๋ค.
MFA๋?
MFA (Micro Frontend Architecture)๋ ํ๋ก ํธ์๋ ์๋น์ค๋ฅผ ์์ ๋จ์๋ก ์ชผ๊ฐ์ด ๊ฐ๋ณ์ ์ผ๋ก ๊ฐ๋ฐโฆ๋ฐฐํฌ๋ฅผ ์งํํ๊ณ , ์ด๋ฅผ ์กฐํฉํ์ฌ ํตํฉ ์๋น์ค๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ๋ก ์ ๋๋ค. ๊ฐ๋ณ ์ฝ๋์ ๋ฆฌ์์ค๋ฅผ ๊ธฐ๋ฅ๋ณ๋ก ๋ถ๋ฆฌํ๊ธฐ ๋๋ฌธ์ ์ ์ง๋ณด์์ ์ฌ์ฌ์ฉ์ด ์ฉ์ดํ๊ณ , ์๋ก ๋ ๋ฆฝ์ ์ธ ์์ ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์กฐ์ง ์ด์์๋ ๋์์ด ๋๋ ๋ฑ ๋๊ท๋ชจ ์๋น์ค ๋๋ ์กฐ์ง์์ ๊ฐ์ ์ ๋ณด์ด๋ ๋ฐฉ์์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.
MFA๋ฅผ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์๋ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ํจํค์ง๋ก ๋ง๋ค์ด ๋น๋ ๊ณผ์ ์์ ํตํฉ์ ํ๋ ๋ฐฉ๋ฒ๋ ์๊ณ , <iframe> ํ๊ทธ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์์ต๋๋ค. ํ์ง๋ง ์ ํฌ ์ธก์์๋ JavaScript ๋ฒ๋ค์ ๋ฐํ์์์ ๋ก๋ํด์ ํฉ์น๋ ๋ฐฉ์์ธ Module Federation์ ๊ณ ๋ คํ๊ณ ์ด์ชฝ์ผ๋ก ํ
์คํธ๋ฅผ ์งํํ๊ธฐ๋ก ํ์ต๋๋ค.
Module Federation ์ ์ฉํด ๋ณด๊ธฐ

์์๋ฅผ ์ํด CRA๋ก ๊ฐ๋จํ๊ฒ 2๊ฐ์ ์ฑ์ ๊ตฌ์ฑํ์ต๋๋ค. ๋ชฉํ๋ ์ฒซ ํ๋ฉด(์ดํ ์ธ๋ถ)์ ์นด๋๋ฅผ ํธ์คํธ๋ก ๋ถ๋ฌ์ค๋ ๊ฒ์
๋๋ค.
์ธ๋ถ ์นด๋๋ ์๋์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ teamName, teamImgUrl ์ ๋ณด๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
ํธ์คํธ ์นด๋๋ ํธ์์ ํ๋์ฝ๋ฉ๋์ด ์์ต๋๋ค.
{
"teamName": "T1",
"teamImgUrl": "<t1-url>",
"playerName": "Faker",
"playerImgUrl": "<faker-url>"
}
Module Federation์ ์ฌ์ฉํ๊ธฐ ์ํด์๋ webpack์ ์ค์ ํด์ผ ํฉ๋๋ค.
์ด๊ธฐํ์๋ npx webpack init ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ๋๋ฐ, ์ง์ ์ค์น๋ฅผ ํด๋ ๋ฉ๋๋ค.
์ฌ๋ฌ ์ค์ ์ค์์๋ ๊ฐ์ฅ ์ค์ํ ๋ถ๋ถ์ webpack.config.js ํ์ผ ์ค์ ์ด์์ต๋๋ค.
const { ModuleFederationPlugin } = require("webpack").container;
const { FederatedTypesPlugin } = require("@module-federation/typescript");
// ...
const federationConfig = {
name: "exportapp",
filename: "remoteEntry.js",
exposes: {
"./Team": "./src/component/Team.tsx",
"./types": "./src/@types/index.ts",
},
shared: {
...deps,
react: { singleton: true, eager: true, requiredVersion: deps.react },
"react-dom": {
singleton: true,
eager: true,
requiredVersion: deps["react-dom"],
},
// ...
},
};
// ...
const config = {
entry: "./src/index.ts",
// ...
plugins: [
// ...
new ModuleFederationPlugin(federationConfig),
new FederatedTypesPlugin({ federationConfig }),
],
// ...
};
// ...
์๋ ์ธ๋ถ ๋ชจ๋์ ์ค์ ํ์ผ์
๋๋ค. federationConfig ๋ณ์์ Module Federation ์ค์ ์ด ๋ค์ด ์๋๋ฐ, ์ฃผ๋ชฉํ ๋ถ๋ถ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
name์ ์ ์ฒด ๋ชจ๋์ ์ด๋ฆ์ผ๋ก, ๋ค๋ฅธ ์ฑ๊ณผ ์ค๋ณต๋์ง ์์์ผ ํฉ๋๋ค.filename์ ๋ด๋ณด๋ผ ํ์ผ์ ์ด๋ฆ์ ๋๋ค.exposes๋ ์ด๋ค ์์ค๋ฅผ ์ด๋ค ์ด๋ฆ์ผ๋ก ๋ด๋ณด๋ผ์ง ๊ฒฐ์ ํฉ๋๋ค.
name๊ณผ ํจ๊ป ๋ชจ๋ ํธ์ถ์ ์ฌ์ฉ๋๊ธฐ ๋๋ฌธ์ ์ ํํ ์ค์ ํด ์ฃผ์ด์ผ ํฉ๋๋ค.
Module Federation์ ํ์์ ์ธ ModuleFederationPlugin ์ธ์, TypeScript์์ ํ์
๊ณต์ ๋ฅผ ์ํด ์ถ๊ฐ๋ก FederatedTypesPlugin์ ์ฌ์ฉํ์์ต๋๋ค. ์ฐ์ํํ์ ๋ค์์๋ ์๋ฐฉํฅ ํ์
๊ณต์ ๋ฅผ ์ํด @module-federation/native-federation-typescript ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ๋๋ฐ, ์ ์ ๊ฒฝ์ฐ ์์ง ์๋ฐฉํฅ ํ์
๊ณต์ ๋ฅผ ๊ณ ๋ คํ ๋จ๊ณ๋ ์๋๋ผ๊ณ ํ๋จํ์ต๋๋ค.
// ...
const federationConfig = {
name: "hostapp",
remotes: {
sample1: "exportapp@http://localhost:3001/remoteEntry.js",
},
shared: {
// ...
},
};
// ...
ํธ์คํธ์ ์ค์ ํ์ผ๋ ๊ฑฐ์ ๋์ผํ์ง๋ง, ๋ชจ๋์ ๋ถ๋ฌ์ค๊ธฐ ์ํด remotes ์ต์
์ ์ค์ ํ์ต๋๋ค. ์ธ๋ถ ๋ชจ๋์์ ์ค์ ํ ์ด๋ฆ๊ณผ ํ์ผ๋ช
, ๊ทธ๋ฆฌ๊ณ ์ ๊ทผ ์ฃผ์๋ฅผ ์ฌ์ฉํด ๊ฐ์ ์
๋ ฅํฉ๋๋ค.
์ด๋ ๊ฒ ์ค์ ์ ๋ง์น๊ณ ์๋น์ค๋ค์ ์ฌ์คํํ๋ฉด ํธ์คํธ์ ํ์
ํ์ผ์ด ์์ฑ๋ฉ๋๋ค.

์์ฑ๋ ํ์ ํ์ผ์ ์ด์ฉํ์ฌ ํธ์คํธ์์ ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ต๋๋ค. VS Code ๊ธฐ์ค ์ฝ๋ ์์ฑ ์์๋ ํ์ ์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ถ๋ฌ์ค๋ ๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.

์นด๋์ ๋ค์ด๊ฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํด๋ ๋ฌธ์ ์์ด ๋ชจ๋์ด ํ์๋์์ต๋๋ค.

๋ง์ฃผ์ณค๋ ๋ฌธ์ ๋ค
- ์ฌ๋ฌ ํ๊ฒฝ์ด ์๊ธฐ ๋๋ฌธ์ ์คํ์ผ ์ถฉ๋ ๋ฌธ์ ๋ ๋ฐ๋์ ๊ณ ๋ คํด์ผ ํ์ต๋๋ค.
์ฒ์์๋ Shadow DOM์ ์๊ฐํ์ต๋๋ค. ์จ๊ฒจ์ง DOM์ ๋ง๋ค์ด ์คํ์ผ ํ๊ทธ๋ฅผ ์ถ๊ฐํ๋ ์์ผ๋ก ๊ฐ๋ณ์ ์ธ ์คํ์ผ ์ ์ฉ์ ๊ตฌํํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋๋ค. ํ์ง๋ง ์ด ๊ฒฝ์ฐ Shadow DOM์ ์ค์ ํ ๋ช ํํ ๊ฒฝ๊ณ๋ฅผ ์ ํด์ผ ํ๋๋ฐ, ํ์ฌ ์ ์ฑ ์ด ๋ชจํธํด์ ๊ตฌํ์ด ์ ๋งคํ๋ค๋ ์๊ฐ์ด ๋ค์์ต๋๋ค. ์ฐ์ ์์ ๋ง ์ฐพ์ ๋๊ณ ํ์ํ ๊ฒฝ์ฐ ์ ์ฉํ๊ธฐ๋ก ํ์ต๋๋ค.
๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์styled-components๋ฑ์ CSS-in-JS ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ์ด ๋ฐฉ๋ฒ์ ํตํด์๋ ์ ์์ ์ผ๋ก ์คํ์ผ ๋ถ๋ฆฌ๊ฐ ์ด๋ฃจ์ด์ง๋ ๊ฒ์ ํ์ธํ์์ต๋๋ค.
์์ ๊ธฐ์ ํ ๋ฐฉ๋ฒ๋ ํด๋์ค๋ช ์ด ์ค๋ณต๋๋ฉด ์ถฉ๋ ๋ฌธ์ ๊ฐ ์์ด, ๋ณ๋์ ๋ด๋ถ ๊ท์น์ ์ ํ๋ ๊ฒ์ด ๊ฐ์ฅ ํ์คํ๋ค๋ ์๊ฒฌ์ ๋ฐ์์ต๋๋ค. (์ธ๋ฌธ๋ ๊ฐ์ฌ๋๋ฆฝ๋๋ค ๐) - Module Federation์ ๋ณ๋์ ์ค์ ์ด ์์ ๊ฒฝ์ฐ ํธ์คํธ์ ์ฐ๊ฒฐ๋ UI ์ค ํ๋๋ผ๋ ๋ก๋์ ์คํจํ๋ค๋ฉด ํธ์คํธ ์ ์ฒด๊ฐ ๋ฉ์ถ๋ ์น๋ช ์ ์ธ ๋ฌธ์ ๊ฐ ์์์ต๋๋ค. ์ด์์์๋ ํด๋น ๋ฌธ์ ์ ๋ํด ๋ ผ์ํ ํ์ ์ด ์๊ณ ์์ธ ์ฒ๋ฆฌ๋ ๋ก์ฐ๋ ๋ฒจ API ๋ฑ์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ผ๋ ์ด์ผ๊ธฐ๊ฐ ์์์ง๋ง, ์ฌ๋ฌ ๊ฐ์ง ์๋๋ฅผ ํด ๋ณธ ๊ฒฐ๊ณผ ์ ๊ธฐ์ค ๊ฐ์ฅ ๊น๋ํ ๋ฐฉ๋ฒ์ Error boundary๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด์์ต๋๋ค. ๋ชจ๋ ๋ค์ด๋ก๋ ์๋ฌ๋ฅผ ์ก๋ ๋ณ๋ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด์ ๊ณต์ ๋ชจ๋์ ๊ฐ์ธ๊ณ , ์๋ฌ ๋ฐ์ ์ ๋ฐ๋ก ์ฒ๋ฆฌํ๋๋ก ํ์์ต๋๋ค.

- ๊ทธ ์ธ webpack ๊ณต์ ๋ฌธ์ ๋ฑ์ ์ฐธ๊ณ ํ์ฌ ์๋ฌ๋ฅผ ํด๊ฒฐํ์์ต๋๋ค.
์ฒดํํด ๋ณด๋ฉฐ ๋๋ ์
- ์์์ ํ์ง๋ง ์๊ฐ๋ณด๋ค ๋ ์ค์ ์ด ๋ณต์กํ์ต๋๋ค. ์์์๋
webpack.config.jsํ์ผ์ ์ผ๋ถ ์ค์ ๋ง ๋ค๋ฃจ์์ง๋งtsconfig.json์ค์ , ํจํค์ง ์ต์ ํ ๋ฑ ์ฌ๋ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด์ผ ํ์ต๋๋ค. ํ ์คํธ ๊ณผ์ ์ด์๊ธฐ ๋๋ฌธ์ ์ผ๋ถ ๋ฌธ์ ๋ ์ฆ์๋ง ์ ์ด ๋๊ณ ๋์ด๊ฐ๊ธฐ๋ ํ์ต๋๋ค. - ๋ณต์ก๋๊ฐ ๋์ ํฐ ์๋น์ค์์๋ ์ด๋ฅผ ๊ฐ์ํ๊ณ ์ฌ์ฉํ ์ ์์ง๋ง, ์๊ท๋ชจ ์๋น์ค์๋ ์ ํฉํ์ง ์๋ค๊ณ ๋๊ผ์ต๋๋ค.
- ์์ง ์ํ๊ณ๊ฐ ๋ฏธ์ฑ์ํ๋ค๊ณ ์๊ฐ๋์์ต๋๋ค. ์๋ฃ๋ ์ฐพ๊ธฐ ์ฝ์ง ์์๊ณ , ๋ฌธ์๋ ์์ ๋ ์ค๋ช
์ด ๋ถ์คํ๊ฑฐ๋ ์ฐธ๊ณ ํ๊ธฐ ํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์์ต๋๋ค.
+) 2024.4์ ๊ธฐ์ค ๊ณ์ ๊ณต์ ํ์ด์ง์ ํ๋ฌ๊ทธ์ธ ๋ฑ์ด ๋ณํ๊ณ ์์ต๋๋ค. - ๊ฐ๋ฐ ํ๊ฒฝ์์ ์ฌ๋ฌ ๊ฐ์ง ์์ํ ๋ฒ๊ทธ๊ฐ ์์์ต๋๋ค. ํนํ webpack ๊ฐ๋ฐ ์๋ฒ์ ํธํ์ด ์ ๋์ง ์๋ ๊ฒ์ผ๋ก ๋ณด์ ๋๋ค.
๋ง์น๋ฉฐ
์ค๋๋ง์ ๊น๊ฒ ํ๋ก ํธ์๋ ๋ถ์ผ๋ฅผ ํ๊ณ ๋ค์ด์ ๊ทธ๋ฐ์ง ์ฝ์ง ์์๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฌ์ค ์ด๊ฒ์ด ์ฃผ๋ ์์ ์ ์๋๊ณ , K8s ํ๊ฒฝ์์ MFA ํ ํ๋ฆฟ์ ๊ตฌ์ถํ๊ณ ๋ฐฐํฌ๊น์ง ์๋ํํ ์ ์๋์ง ๊ฒ์ฆํ๋ ๊ฒ์ด ์ต์ข ๋ชฉ์ ์ ๋๋ค. ์ดํ ์งํ์ฌํญ์ด ์๊ธฐ๋ฉด ์ถ๊ฐ๋ก ์ ์ด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ ์ ์์ ๋ด์ญ์ ์๋ Repository์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
Repository ๋ฐ๋ก๊ฐ๊ธฐ
์ฐธ๊ณ ์๋ฃ
- ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ๋ฏธ๋, Module Federation์ ์ ์ฉ
TypeScript ํ์ ๋ฌธ์ ๋ฑ ๋ฌธ์ ์ํฉ์ ๊ฒํ ํ๊ณ ํด๊ฒฐํ๋ ๋ฐ ๋์์ ๋ฐ์์ต๋๋ค. - Webpack 5 Module Federation์ผ๋ก Micro-Frontends ์ด์ํ๊ธฐ
Module Federation์ ์ด๊ธฐ ๊ฐ๋ ์ ์ก๋ ๋ฐ ๋งค์ฐ ํฐ ๋์์ด ๋์์ต๋๋ค. - Module Federation ๊ณต์ ์์ Repository
- ๊ทธ ์ธ ๊ฐ์ข ๊ณต์ ๋ฌธ์