Skip to content

장애 범위 축소

마이크로 프론트엔드에서 단일 장애 지점(SPOF)을 회피하고 장애 영향을 최소화하는 전략과 한계를 정리한다.

학습 목표

  1. 마이크로 프론트엔드의 핵심 목표인 단일 장애 지점 회피의 의미를 설명할 수 있다.
  2. 에러 바운더리, 폴백 UI, 그레이스풀 디그레이데이션의 구현 전략을 제시할 수 있다.
  3. 모니터링과 알림 체계를 통해 장애를 조기에 감지하는 방법을 이해한다.
  4. 마이크로 프론트엔드 장애 대응의 한계와 트레이드오프를 인식한다.

1. 마이크로 프론트엔드의 두 가지 핵심 목표

마이크로 프론트엔드의 존재 이유를 두 가지로 정리할 수 있다.

목표설명
단일 장애 지점(SPOF) 회피하나의 마이크로 앱에 문제가 생겨도 나머지는 정상 동작한다
복잡도의 관리 가능한 분할전체 앱의 복잡도를 팀이 감당할 수 있는 수준으로 쪼갠다

이 두 목표는 하나만 달성해서는 의미가 없다. 코드를 분리했지만 모든 리소스를 같은 서버에서 서빙한다면, 서버 장애 시 전체가 다운되므로 SPOF를 회피한 것이 아니다.


2. 에러 바운더리 (Error Boundary)

개념

에러 바운더리는 하위 컴포넌트 트리에서 발생한 JavaScript 오류를 잡아내어 전체 앱의 크래시를 방지하는 React 패턴이다. 마이크로 프론트엔드에서는 각 원격 모듈을 에러 바운더리로 감싸서 하나의 마이크로 앱 오류가 전체로 전파되는 것을 차단한다.

구현 전략

javascript
// RemoteAppWrapper.jsx
class RemoteErrorBoundary extends React.Component {
  state = { hasError: false, error: null };

  static getDerivedStateFromError(error) {
    return { hasError: true, error };
  }

  componentDidCatch(error, errorInfo) {
    // 모니터링 서비스로 에러 보고
    errorReporter.captureException(error, {
      extra: {
        componentStack: errorInfo.componentStack,
        remoteName: this.props.remoteName,
      },
    });
  }

  render() {
    if (this.state.hasError) {
      return <FallbackUI remoteName={this.props.remoteName} />;
    }
    return this.props.children;
  }
}

// Shell에서 사용
function App() {
  return (
    <Layout>
      <RemoteErrorBoundary remoteName="auth">
        <Suspense fallback={<Loading />}>
          <AuthApp />
        </Suspense>
      </RemoteErrorBoundary>

      <RemoteErrorBoundary remoteName="dashboard">
        <Suspense fallback={<Loading />}>
          <DashboardApp />
        </Suspense>
      </RemoteErrorBoundary>
    </Layout>
  );
}

에러 바운더리 배치 원칙

위치역할폴백 UI
Shell 최상위전체 앱 크래시 방지전체 에러 페이지
각 마이크로 앱 감싸기개별 앱 장애 격리해당 영역 대체 UI
각 프래그먼트 감싸기프래그먼트 로딩 실패 격리빈 영역 또는 기본 UI
비핵심 기능 감싸기부가 기능 장애 격리기능 숨김

3. 폴백 UI와 그레이스풀 디그레이데이션

폴백 UI 설계

마이크로 앱 로딩 실패 시 보여주는 대체 UI는 사용자 경험의 핵심이다.

그레이스풀 디그레이데이션 단계

"우아한 성능 저하(Graceful Degradation)"란 일부 기능이 실패하더라도 전체 서비스가 멈추지 않고 가능한 범위 내에서 계속 동작하는 것을 말한다.

단계상태사용자 경험
1단계: 정상모든 마이크로 앱 정상 로드전체 기능 사용 가능
2단계: 부분 장애일부 마이크로 앱 로드 실패실패한 영역에 폴백 UI 표시, 나머지 정상
3단계: 핵심만 동작다수 마이크로 앱 실패Shell과 핵심 기능만 동작, 비핵심 기능 숨김
4단계: 최소 서비스Shell만 동작안내 페이지와 고객센터 연결만 제공

구현 패턴: 동적 임포트 + 재시도

javascript
// 재시도 로직이 포함된 동적 임포트
function loadRemoteApp(remoteName, retries = 3) {
  return new Promise((resolve, reject) => {
    const attempt = (remaining) => {
      import(/* webpackChunkName: "[request]" */ `${remoteName}/App`)
        .then(resolve)
        .catch((error) => {
          if (remaining > 0) {
            setTimeout(() => attempt(remaining - 1), 1000 * (4 - remaining));
          } else {
            reject(error);
          }
        });
    };
    attempt(retries);
  });
}

4. 인프라 레벨 장애 회피

코드 레벨의 에러 바운더리만으로는 충분하지 않다. 서버, 네트워크, CDN 레벨에서도 SPOF를 제거해야 한다.

인프라 분리 원칙

원칙구체적 방법
서버 분리각 마이크로 앱의 정적 리소스를 별도 서버 또는 별도 CDN 버킷에 배포
CDN 다중화메인 CDN 장애 시 폴백 CDN으로 자동 전환
도메인 분리auth.cdn.example.com, dashboard.cdn.example.com 등 도메인 분리
헬스체크각 마이크로 앱 서버의 상태를 주기적으로 확인
캐시 전략CDN 캐시를 활용하여 오리진 서버 장애 시에도 캐시된 버전 서빙

비용 트레이드오프

마이크로 프론트엔드에서 인프라를 분리하면 서버 비용이 증가한다. 이는 피할 수 없는 트레이드오프다.

  • 마이크로 앱이 5개이면 최소 5개의 배포 대상이 필요하다.
  • 이중화까지 하면 10개 이상의 서버/CDN 구성이 필요할 수 있다.
  • Vercel, Cloudflare Pages, AWS S3 + CloudFront 같은 SaaS를 활용하면 비용을 낮출 수 있지만, 그래도 모놀리식보다는 비용이 높다.

분리한 만큼 비용이 늘어나므로, 무조건 쪼개는 것이 아니라 관리가 가능한 수준으로 적절하게 나누는 것이 중요하다.


5. 모니터링과 알림

장애를 완전히 예방할 수는 없다. 빠르게 감지하고 대응하는 것이 핵심이다.

모니터링 대상

마이크로 앱별 모니터링

지표임계값 예시알림 조건
원격 모듈 로드 실패율5% 초과즉시 알림
JS 에러율1% 초과5분 내 알림
LCP (Largest Contentful Paint)2.5초 초과30분 추이 확인 후 알림
API 응답 시간p95 > 3초10분 내 알림
에러 바운더리 트리거 횟수시간당 100회 초과즉시 알림

실무 도구

도구용도
Sentry프론트엔드 에러 추적, 소스맵 연동
Datadog RUMReal User Monitoring, 성능 지표 수집
Grafana + Prometheus인프라 메트릭 시각화
PagerDuty온콜 알림 및 인시던트 관리
Lighthouse CI배포 시 성능 회귀 자동 감지

장애 대응 프로세스

  1. 감지: 모니터링 시스템이 이상 지표를 감지하여 알림을 발송한다.
  2. 격리: 문제가 있는 마이크로 앱을 이전 버전으로 롤백하거나 기능 플래그로 비활성화한다.
  3. 분석: 에러 로그, 배포 이력, 변경 사항을 확인하여 원인을 파악한다.
  4. 수정: 원인을 수정하고 테스트한 후 재배포한다.
  5. 회고: 장애 원인, 대응 과정, 개선 사항을 팀 전체와 공유한다.

6. 마이크로 프론트엔드의 한계 인식

무조건 쪼개는 것이 답이 아니다

마이크로 프론트엔드를 도입할 때 가장 흔한 실수는 필요 이상으로 쪼개는 것이다.

  • 쪼갠 만큼 관리 포인트가 늘어난다.
  • 코드 관리는 쉬워지지만 배포 관리는 복잡해진다.
  • 인프라 비용이 분리한 만큼 증가한다.
  • 중복 코드가 발생하는 것을 두려워하면 안 된다. 독립 배포를 위해 어느 정도의 코드 중복은 감수해야 한다.

적절한 분할의 기준

분할 기준적절과도
팀 규모팀당 2-3개 마이크로 앱팀당 10개 이상
복잡도각 앱이 관리 가능한 크기이미 단순한 것을 더 쪼갬
배포 주기팀별 배포 주기가 다름모든 앱을 동시에 배포
장애 격리앱 간 독립적 운영공통 서버에서 전부 서빙

중복 코드에 대한 인식 전환

개발자 입장에서 중복 코드를 유지하는 것은 잘못된 일처럼 느껴진다. 하지만 마이크로 프론트엔드에서는 독립 배포를 위해 중복을 감수해야 하는 경우가 있다.

  • 중복된 코드조차 잘 관리하는 수준이라면 문제가 없다.
  • 중복을 줄이기 위해 공통 패키지를 만드는 순간, 배포의 독립성이 훼손될 수 있다.
  • 빌드타임에 공유되는 패키지는 보수적으로 변경하고, 마이크로 앱 내부의 비즈니스 로직은 빠르게 변경한다.

핵심 정리

전략핵심
SPOF 회피인프라를 분리하여 하나의 장애가 전체로 파급되지 않도록 한다
에러 바운더리각 마이크로 앱을 에러 바운더리로 감싸서 런타임 에러를 격리한다
그레이스풀 디그레이데이션부분 장애 시 나머지 기능은 계속 동작하도록 설계한다
모니터링/알림장애를 빠르게 감지하고 대응하는 체계를 구축한다
적절한 분할관리 가능한 수준으로만 나누고, 중복 코드를 두려워하지 않는다

마이크로 프론트엔드는 은총알(Silver Bullet)이 아니다. 단일 장애 지점 회피와 복잡도의 관리 가능한 분할이라는 명확한 목표가 있을 때 의미가 있다. 이 목표가 필요하지 않은 프로젝트에서는 모놀리식이 더 나은 선택일 수 있다.


다음 단계

지금까지 마이크로 프론트엔드의 보안, 팀 운영, 배포, 개발 환경, 장애 대응까지 전반적인 운영 전략을 살펴보았다. 다음 장에서는 이러한 전략이 실제 프로덕트에 어떻게 적용되었는지 Dooray 프로젝트 사례를 통해 확인한다.

다음 문서: ../17-사례-연구-Dooray/01-Dooray-프로젝트-소개.md