Case Study · Micro Frontend Platform

하나의 도메인, 열 개의 독립 배포 —
Micro Frontend 백오피스 플랫폼

팀마다 백오피스가 따로 있어 운영자는 여러 URL과 로그인을 오갔고,
하나로 합치자니 한 줄 변경에도 전체 빌드 25분을 기다려야 했습니다.

Module Federation으로 화면은 런타임에 합치고, 빌드·배포는 팀별로 분리했습니다.

자비스앤빌런즈(삼쩜삼) · 플랫폼 설계·구축·운영 (기여도 90%) · 온보딩 체계 설계 — 프론트엔드 개발자가 아닌 구성원들이 어드민 10여 개 직접 제작

Remote 10개모노레포 6 + 별도 레포 4별도 레포는 프론트엔드 팀 밖에서 제작
25분 → 3분CI/CD — 변경된 앱만 선택 빌드turbo-ignore
12개 그룹단일 도메인에서 운영되는 대메뉴Role 기반 권한 필터
싱글턴 4개react · dom · router · query 단일 인스턴스 공유MF shared
01 · Problem

흩어지면 운영이 느리고, 합치면 배포가 느립니다

Before — 어드민이 팀마다 따로

콘텐츠 어드민
🔒 별도 로그인UI 제각각
대리점 어드민
🔒 별도 로그인권한 제각각
앱 어드민 + N개…
🔒 별도 로그인URL 제각각

⚠ 합치면? 한 팀의 한 줄 변경에도 전체 빌드 25분 + 배포 대기 줄

After — 한 화면에 모든 팀

통합 어드민 — 로그인 1번
콘텐츠 관리 모바일 앱 핵심 서비스 업무 큐 계정·권한 …12개 그룹

색점 하나가 팀(remote) 하나 — 화면은 하나지만 배포는 여전히 팀별, 변경된 앱만 3분

02 · Architecture

Host는 뼈대를, Remote는 화면만

Host가 인증·레이아웃·라우팅·권한을 소유하고, Remote는 ./App 진입점 하나만 노출합니다.

Host — 공통 기능 소유

로그인부터 메뉴 권한까지, 공통은 전부 Host가

인증로그인·유저 API 처리 → Role 확정 — 로그인 1번을 모든 remote가 공유
권한 메뉴Role 기반 재귀 필터로 대메뉴 12그룹 구성 — 권한 없는 메뉴는 아예 안 보임
레이아웃GNB · SNB · 서브헤더 · 테마 — remote는 콘텐츠 영역만 채움
remote 로드lazy(지연 로드) + Error Boundary(장애 격리·재시도) + Suspense(로딩)

공유 싱글턴 4개: react react-dom react-router react-query — 열 개의 앱이 하나의 React 트리·라우터·쿼리 캐시를 씁니다

런타임에 remoteEntry.js 로드 — 빌드 타임 결합 없음
Remote ×10 — 팀별 독립 개발·배포

자기 도메인 화면 + 내부 라우팅만 책임

── 모노레포  ·  ┄ 별도 레포
콘텐츠·에셋모바일 앱핵심 서비스제휴 채널업무 큐상담 시스템 계정·권한모니터링개발자 도구데이터 수집

점선 remote는 프론트엔드 팀 밖에서 개발·배포되는 어드민 — 레포가 달라도 같은 화면에서 동작합니다

모든 remote는 host 없이 단독 실행도 가능합니다 — 각 팀은 자기 앱만 띄워서 개발합니다

① 콘텐츠팀 — push
fix: 콘텐츠 카드 정렬 버그 수정 — 1개 파일
CI 매트릭스 — 10개 앱
② turbo-ignore — 변경된 앱만 빌드
CDN 업로드
③ 콘텐츠 remote 산출물 교체
remoteEntry.jsno-cacheentry.a1f3entry.b7e2
chunk-[hash].js장기 캐시변경 없는 청크는 그대로 재사용
사용자 다음 진입
④ Host — 재배포 없이 신버전
통합 어드민 Host 재배포 0회
콘텐츠 관리 모바일 앱 업무 큐
콘텐츠 목록 v1.7
변경된 앱만 빌드하고, 새 버전은 사용자의 다음 진입 때 바로 반영되며, Host는 그대로 둡니다 — 이 세 가지가 독립 배포를 만듭니다.
03 · Fault Isolation

한 팀의 실수가 다른 팀 화면을 멈추지 못하게

Remote마다 Error Boundary로 감싸 로드 실패·렌더 에러를 그 화면 안에 가둡니다.

장애 격리 시뮬레이션 — Error Boundary 동작 재구성
문제가 생긴 remote만 Fallback으로 바뀌고, 다른 메뉴는 그대로 동작합니다. 다시 시도는 실제 구현처럼 리마운트(key 교체)로 remote 모듈 로드부터 다시 수행합니다.
04 · Deep-dive — Inheritance

공통 인프라는 Host가 주고, Remote는 물려받습니다

공유 싱글턴 4개 — React 트리·라우터·쿼리 캐시가 전부 같은 상속 구조입니다.
대표 사례가 QueryClient입니다: Host 안에서는 상속해 캐시를 공유하고, 단독 실행이면 자체 생성합니다.

// remote App.tsx — 자기 Provider보다 위의 Context를 읽는다
const standaloneQueryClient = new QueryClient()

const App = () => {
  // Host 안이면 Host의 클라이언트를 상속해 캐시 공유, standalone이면 자체 생성
  const queryClient = useContext(QueryClientContext) ?? standaloneQueryClient
  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
}

단, 조건이 하나 있습니다 — Host와 Remote가 같은 react-query 인스턴스를 써야 합니다. 인스턴스가 다르면 Context도 달라서 상속이 끊기기 때문입니다.

싱글턴이 아니면 — 상속 자체가 불가능
Host 번들 — react-query 사본 A → Context A로 제공
Remote 번들 — react-query 사본 B → Context B를 조회

⚠ Remote의 훅이 Host의 Provider를 찾지 못합니다 — 서로 다른 Context를 보고 있기 때문

싱글턴이면 — Context가 하나라 상속 성립
MF shared — react-query 단일 인스턴스 → Context도 하나
react · react-dom · react-router도 같은 원리로 공유

MF shared의 본질은 버전 협상이 아니라 모듈 인스턴스 공유입니다

상속의 실질 효과 — 쿼리 키가 remote 사이에서 공유됩니다

콘텐츠 remote useQuery(['auth/me']) ──┐ 업무 큐 remote useQuery(['auth/me']) ──┴─→ 네트워크 요청 1번 — 두 번째는 캐시 히트

열 개의 remote가 공통으로 부르는 API(유저·권한·공통 코드)가 화면을 오갈 때마다 다시 호출되던 것이, 상속 후에는 한 번의 요청과 캐시 재사용으로 바뀝니다.
자기 도메인 키만 무효화하는 컨벤션으로 관리하고, 진짜 격리가 필요한 앱은 shared 미등록으로 opt-out합니다.

05 · Reliability

독립 배포를 안전하게 만드는 원칙들

실제 사고를 겪으며 만든 규칙들입니다. 지키는 일은 사람의 주의가 아니라 CI와 설정에 맡겼습니다.

사고 기록 — 캐럿(^) 하나가 만든 전체 흰 화면
별도 레포의 remote가 MF 플러그인을 ^1.8.1로 선언했습니다. 캐럿은 "1.x 최신이면 아무거나"라는 뜻이라, 설치 시점에 1.20이 깔렸습니다.
Host(1.8.1)와 remote(1.20)가 서로 다른 버전의 MF 런타임으로 만나자 — 에러 로그 한 줄 없이 화면 전체가 하얗게 떴습니다.
React 버전으로 같은 사고를 한 번 더 겪고 나서, "공유 라이브러리는 정확한 버전으로 고정하고, remote는 Host보다 높은 버전을 쓰지 않는다"를 원칙으로 만들었습니다.
장치지키는 것
버전 불일치 차단모노레포 앱들은 루트 pnpm.overrides로 버전을 한 곳에서 통일하고, 프론트 팀이 직접 관리하지 않는 별도 레포는 CI가 검사해 어긋나면 빌드 실패 + 슬랙 알림 (사고 2건 후 원칙화)
remoteEntry no-cacheremote를 배포해도 구버전이 로드되는 함정 — 엔트리만 캐시 제외, 청크는 해시로 장기 캐시
브랜치 프리뷰 + 자동 회수브랜치를 올리면 그 브랜치만의 프리뷰 주소가 자동으로 생기고, 브랜치를 지우면 프리뷰와 배포 리소스도 자동으로 정리됩니다 (CloudFront Multi-Tenant)
06 · Self-serve

프론트엔드 개발자가 아니어도 어드민을 만듭니다

플랫폼이 공통 문제를 미리 풀어두면, 각 팀에게 남는 일은 자기 화면뿐입니다.

플랫폼이 미리 제공하는 것

  • 로그인·인증 — 템플릿에 이미 연결돼 있음
  • 공통 레이아웃 · 메뉴 권한
  • 배포 파이프라인 — 설정 파일 한 줄이면 CI에 편입
  • Module Federation 연결 설정
  • 온보딩 가이드 + Claude Code 스킬

팀이 할 일

  • 자기 도메인 화면 개발 — 그게 전부입니다

그 결과 프론트엔드 개발자가 아닌 구성원들이 10개에 달하는 어드민을 대부분 질문 없이 직접 만들었고, 회사 전체 구성원이 사용하고 있습니다.