테마
설계 패턴과 서비스 분리
커리어업 플랫폼에 App Shell 패턴, 인증 공유, 스타일 격리 전략을 적용하고, URL 경로 기반으로 서비스를 분리하여 팀 오너십을 수립한다.
학습 목표
- 마이크로프론트엔드 설계 시 풀어야 할 세 가지 핵심 문제를 식별한다
- App Shell 패턴을 이해하고 Browser Router와 Memory Router의 조합 방식을 파악한다
- Shell 기반 인증 공유와 이벤트 시스템의 구조를 설계할 수 있다
- CSS 스타일 격리 전략을 수립하고 UIKit 설계 방향을 결정한다
- URL 경로 기반 서비스 분리와 팀 오너십 구성을 설계할 수 있다
1. MFE 설계에서 풀어야 할 핵심 문제
커리어업을 마이크로프론트엔드로 설계할 때 반드시 해결해야 할 세 가지 문제가 있다. 이 문제들은 모두 각 마이크로앱이 독립적으로 개발/배포되었을 때에도 문제 없이 통합되도록 하는 것과 관련된다.
| 순서 | 문제 영역 | 핵심 질문 |
|---|---|---|
| 1 | 라우팅 통합 | 브라우저 URL과 각 마이크로앱의 내부 라우팅을 어떻게 동기화하는가? |
| 2 | 인증 공유 | Shell의 로그인 정보를 각 마이크로앱에 어떻게 전달하는가? |
| 3 | 스타일 격리 | 같은 HTML 문서 안에서 앱 간 CSS 충돌을 어떻게 방지하는가? |
2. 설계 패턴 1: App Shell + 라우팅
2.1 App Shell의 역할
App Shell은 커리어업 플랫폼의 메인 진입점이자 유일한 호스트(Host) 앱이다. 사용자가 서비스에 접근하면 가장 먼저 Shell이 로드되고, Shell이 브라우저 URL을 해석하여 적절한 마이크로앱을 동적으로 불러온다.
2.2 Browser Router vs Memory Router
Shell과 마이크로앱은 서로 다른 라우터를 사용한다. 이 두 라우터 간의 동기화가 핵심이다.
| 구분 | Browser Router (Shell) | Memory Router (마이크로앱) |
|---|---|---|
| 위치 | App Shell | 각 마이크로앱 |
| URL 반영 | 브라우저 주소창에 직접 반영 | 메모리에서만 관리 (주소창 변경 없음) |
| 역할 | URL 경로를 해석하여 마이크로앱 결정 | Shell로부터 전달받은 경로로 내부 네비게이션 |
| 통신 방식 | 커스텀 이벤트로 마이크로앱에 전달 | 커스텀 이벤트로 Shell에 알림 |
2.3 라우팅 동기화 흐름
라우팅 동기화는 양방향으로 이루어진다:
Shell -> 마이크로앱 (외부 네비게이션)
- 사용자가 GNB에서 "교육" 메뉴 클릭
- Browser Router가 URL을
/education으로 변경 - Shell이
[shell-navigate]커스텀 이벤트 발행 - 교육 마이크로앱의 Memory Router가 이벤트를 수신하여 내부 라우팅 처리
마이크로앱 -> Shell (내부 네비게이션)
- 교육 앱 내에서 사용자가 특정 카테고리 클릭
- Memory Router가 내부 경로를
/education/frontend로 변경 - 교육 앱이
[app-navigate]커스텀 이벤트 발행 - Shell의 Browser Router가 이벤트를 수신하여 브라우저 URL 동기화
이 양방향 이벤트 로직은 Shell과 모든 마이크로앱에서 반복되므로, shell-router라는 공통 패키지로 추상화한다. 이 패키지가 수정되면 전체 앱의 재배포가 필요하므로, 인터페이스 안정성이 매우 중요하다.
3. 설계 패턴 2: 인증 공유
3.1 Shell 중심 인증 아키텍처
인증은 App Shell에서 일괄 관리한다. 각 마이크로앱은 별도의 React 앱으로 독립 실행되므로, Shell의 인증 상태가 자동으로 전파되지 않는다. 따라서 이벤트 기반 인증 정보 교환 시스템이 필요하다.
| 항목 | 설명 |
|---|---|
| 인증 제공자 | Auth0 (SaaS) |
| 인증 관리 위치 | App Shell |
| 토큰 저장 | Shell의 메모리 |
| 마이크로앱 전달 | 커스텀 이벤트 시스템 |
| 미인증 처리 | Shell에서 마이크로앱 접근 차단 |
인증 공유 흐름:
- Shell이 Auth0를 통해 로그인 처리
- 로그인 성공 시 토큰과 사용자 정보를 Shell 메모리에 보관
- 마이크로앱이
getUserAsync()함수를 호출하여 Shell에 사용자 정보 요청 - Shell의
useUserEvent()훅이 요청을 수신하고 사용자 정보를 이벤트로 응답 - 마이크로앱이 수신한 토큰으로 자체 백엔드 API 호출
미인증 상태에서는 Shell이 마이크로앱 로드 자체를 차단하여 보안을 확보한다.
3.2 인증 관련 모듈 구성
인증 공유에 필요한 훅과 함수는 shell-router 패키지에 포함된다:
| 모듈 | 위치 | 역할 |
|---|---|---|
useUserEvent | Shell에서 사용 | 마이크로앱의 사용자 정보 요청을 수신하고 응답 |
getUserAsync | 마이크로앱에서 사용 | Shell에 사용자 정보를 요청하고 응답을 대기하는 비동기 함수 |
4. 설계 패턴 3: 스타일 격리
4.1 스타일 충돌 문제
커리어업의 모든 마이크로앱은 같은 HTML 문서(document) 안에 렌더링된다. Shadow DOM을 사용하지 않으므로, CSS 클래스 이름이 충돌할 수 있다. 이를 해결하기 위해 명명 규칙 기반 격리 전략을 사용한다.
4.2 스타일 격리 전략
| 전략 | 설명 |
|---|---|
| Prefix 규칙 | 각 마이크로앱은 고유 접두사를 사용한다 (예: post-, net-, edu-, job-) |
| 팀 자율 기술 | prefix 규칙만 지키면 Sass, CSS Modules, Tailwind 등 자유롭게 선택 |
| UIKit 기본 기술 | 공유 컴포넌트는 특정 기술에 의존하지 않는 기본 CSS로 작성 |
| Global Style | UIKit의 global.css에서 CSS Reset과 전역 스타일 정의 |
4.3 접두사 규칙 예시
css
/* UIKit 공통 컴포넌트 */
.cu-button { /* CareerUp 공통 */ }
.cu-card { }
/* 포스팅 앱 */
.post-editor { }
.post-feed-item { }
/* 네트워킹 앱 */
.net-friend-list { }
.net-recommend-card { }
/* 교육 앱 */
.edu-course-card { }
.edu-progress-bar { }
/* 채용 앱 */
.job-listing { }
.job-apply-form { }5. 서비스 분리 기준: URL 경로 기반
5.1 분리 기준 복습
서비스를 나누는 세 가지 기준이 있다:
| 기준 | 방법 | 커리어업 적용 |
|---|---|---|
| 페이지 유형 분류 | 모든 페이지를 나열하고 유형별로 팀에 배분 | GNB 메뉴가 곧 페이지 유형 |
| 고객 요구사항 중심 | 고객 요구사항을 기준으로 팀 구성 | 글쓰기, 인맥관리, 학습, 취업이 명확한 요구사항 |
| 도메인 주도 설계 | 바운디드 컨텍스트로 팀 경계 설정 | 각 서비스의 도메인이 명확히 분리됨 |
커리어업은 GNB 메뉴가 곧 도메인 경계이므로, URL 경로 기반 분리가 가장 자연스럽다.
5.2 경로 기반 서비스 매핑
| URL 경로 | 마이크로앱 | 담당 팀 | 설명 |
|---|---|---|---|
/ | Shell | 플랫폼 팀 | 메인 페이지, GNB, 인증 |
/posting/* | Posting | 포스팅 팀 | 글 작성, 피드, 댓글 |
/networking/* | Network | 네트워킹 팀 | 일촌 관리, 추천 |
/education/* | Education | 교육 팀 | 교육 콘텐츠, 수강 |
/jobs/* | Jobs | 채용 팀 | 채용 공고, 지원 |
6. 팀 구성과 오너십
6.1 팀 구조
| 팀 | 소유 앱/패키지 | 핵심 책임 |
|---|---|---|
| 플랫폼 팀 | Shell, UIKit, shell-router | 라우팅, 인증, 공통 UI, 인프라 |
| 포스팅 팀 | Posting 앱 | 콘텐츠 작성/조회, 소셜 기능 |
| 네트워킹 팀 | Network 앱, 일촌 맺기 프래그먼트 | 인맥 관리, 일촌 위젯 |
| 교육 팀 | Education 앱 | 교육 콘텐츠 제공, 수강 관리 |
| 채용 팀 | Jobs 앱, 추천 채용 프래그먼트 | 채용 공고 관리, 추천 위젯 |
6.2 오너십 원칙
- 각 팀은 자신의 마이크로앱에 대해 개발, 테스트, 배포의 전체 라이프사이클을 책임진다
- 프래그먼트를 제공하는 팀(네트워킹, 채용)은 해당 프래그먼트의 인터페이스 안정성을 보장한다
- 플랫폼 팀은 Shell과 공통 패키지의 안정성을 보장하고, 다른 팀의 독립 개발을 지원한다
- 공통 패키지 수정은 전체 재배포를 트리거하므로, 변경에 신중해야 한다
핵심 정리
- MFE 설계의 세 가지 핵심 문제: 라우팅 통합, 인증 공유, 스타일 격리
- App Shell이 Browser Router로 URL을 해석하고, 마이크로앱은 Memory Router로 내부 네비게이션을 처리한다. 양방향 커스텀 이벤트로 동기화한다.
- 인증은 Shell이 Auth0로 일괄 관리하고, 이벤트 시스템(
useUserEvent/getUserAsync)으로 마이크로앱에 전달한다 - 스타일은 접두사(prefix) 명명 규칙으로 격리하고, 각 팀은 규칙 내에서 자유롭게 기술을 선택한다
- 공유 UIKit 컴포넌트는 특정 CSS-in-JS 기술에 의존하지 않고 기본 CSS로만 작성한다
- URL 경로 기반으로 서비스를 분리하며, 각 GNB 메뉴가 하나의 마이크로앱에 대응한다
- 5개 팀(플랫폼, 포스팅, 네트워킹, 교육, 채용)이 각자의 앱/프래그먼트를 소유한다
다음 단계
다음 문서 03-모노레포-환경-구축에서는 pnpm 워크스페이스와 Turborepo를 사용하여 실제 모노레포 환경을 구축하고, apps/와 packages/ 디렉터리 구조를 설계하며, 개발 환경 설정을 완성한다.