회복성(Resilience) 이란 시스템의 일부에 장애가 발생하더라도 전체 시스템이 완전히 중단되지 않고, 장애를 감지·격리·복구하여 정상 상태로 되돌아올 수 있는 능력을 말한다.
모놀리식 아키텍처에서는 하나의 장애가 전체 애플리케이션을 멈추게 할 수 있지만, MSA에서는 각 서비스가 독립적으로 배포·운영되기 때문에 장애를 해당 서비스 내부로 격리(Isolation) 할 수 있다. 단, 서비스 간 네트워크 통신이 필수적이므로 장애 전파 가능성도 함께 높아진다. 따라서 MSA에서 회복성 설계는 선택이 아닌 필수다.
핵심 원칙: "장애는 반드시 발생한다" 를 전제로, 장애가 발생했을 때 어떻게 대응할 것인가를 설계 단계부터 고려해야 한다.
| 유형 | 설명 |
|---|---|
| 통신 지연 (Latency) | 서비스 간 호출 시 응답이 비정상적으로 느려지는 현상 |
| 연결 실패 (Connection Failure) | 대상 서비스에 아예 연결이 되지 않는 상태 |
| 타임아웃 (Timeout) | 요청을 보냈으나 정해진 시간 내에 응답을 받지 못하는 상태 |
| DNS 장애 | 서비스 디스커버리 또는 DNS 해석 실패로 대상 서비스를 찾지 못하는 경우 |
| 유형 | 설명 |
|---|---|
| 서비스 다운 (Crash) | 서비스 인스턴스가 비정상 종료되어 요청을 처리할 수 없는 상태 |
| 메모리 부족 (OOM) | 메모리 누수 또는 과도한 부하로 인한 OutOfMemoryError 발생 |
| 무한 루프 / 교착 상태 | 내부 로직 결함으로 서비스가 응답 불가 상태에 빠지는 현상 |
| 배포 오류 | 잘못된 버전 배포, 설정 오류 등으로 서비스가 정상 동작하지 않는 경우 |
| 유형 | 설명 |
|---|---|
| 서버/컨테이너 장애 | 물리 서버 또는 컨테이너(Pod)가 비정상 종료되는 경우 |
| 데이터베이스 장애 | DB 연결 풀 고갈, 복제 지연, 데이터 손상 등 |
| 메시지 브로커 장애 | Kafka, RabbitMQ 등 메시지 큐의 장애로 비동기 통신이 중단되는 경우 |
| 로드 밸런서 장애 | 트래픽 분산 장치의 오작동으로 특정 인스턴스에 트래픽이 집중되는 경우 |
하나의 서비스 장애가 이를 호출하는 상위 서비스들로 전파되어 시스템 전체가 연쇄적으로 장애 상태에 빠지는 현상이다. MSA에서 가장 위험한 장애 유형이며, 회복성 패턴의 주요 방어 대상이다.
[서비스 A] → [서비스 B] → [서비스 C (장애 발생)]
↑
응답 지연 → B도 지연 → A도 지연
스레드 풀 고갈 → 전체 시스템 마비
연속적인 호출 실패가 감지되면 회로를 열어(Open) 더 이상의 요청을 차단하고, 일정 시간 후 다시 시도하여 정상 여부를 확인하는 패턴이다.
상태 전이:
[Closed] --실패율 초과--> [Open] --대기 시간 경과--> [Half-Open]
↑ |
+------ 성공 확인 --------------------------------------+
대표 구현체: Resilience4j, Hystrix(Deprecated), Istio
일시적인 장애(Transient Failure)에 대해 일정 횟수만큼 재시도하는 패턴이다.
| 항목 | 설명 |
|---|---|
| 최대 재시도 횟수 | 일반적으로 2~3회 |
| 재시도 간격 | 고정 간격 또는 지수 백오프(Exponential Backoff) |
| 재시도 조건 | 5xx 에러, 타임아웃 등 일시적 장애에만 적용 |
| 주의점 | 멱등성(Idempotency)이 보장되지 않는 요청에는 적용하지 않아야 한다 |
요청 → 실패 → 대기(100ms) → 재시도 → 실패 → 대기(200ms) → 재시도 → 성공
외부 서비스 호출 시 최대 대기 시간을 설정하여, 응답이 없으면 즉시 실패 처리하는 패턴이다. 스레드나 커넥션이 무한정 점유되는 것을 방지한다.
주 서비스 호출이 실패했을 때 대체 로직을 실행하는 패턴이다.
| 전략 | 설명 |
|---|---|
| 기본값 반환 | 캐시된 데이터 또는 미리 정의된 기본값을 반환 |
| 대체 서비스 호출 | 다른 서비스나 API를 통해 유사한 결과를 제공 |
| 기능 축소 (Graceful Degradation) | 핵심 기능만 유지하고 부가 기능을 일시 제거 |
선박의 격벽 구조에서 유래한 패턴으로, 서비스 호출별로 리소스(스레드 풀, 커넥션 풀)를 분리하여 하나의 장애가 전체 리소스를 고갈시키지 않도록 격리하는 패턴이다.
[서비스 A]
├── 스레드 풀 1 (서비스 B 호출용) → 최대 10개
├── 스레드 풀 2 (서비스 C 호출용) → 최대 5개
└── 스레드 풀 3 (서비스 D 호출용) → 최대 8개
→ 서비스 C가 장애 → 스레드 풀 2만 고갈, 나머지는 정상 동작
특정 서비스나 클라이언트로부터의 요청 속도를 제한하여 과부하를 방지하는 패턴이다.
| 장애 유형 | 적용 패턴 | 목적 |
|---|---|---|
| 일시적 통신 실패 | 재시도 + 지수 백오프 | 일시적 장애 자동 복구 |
| 지속적 서비스 장애 | 서킷 브레이커 | 장애 전파 차단 및 빠른 실패 |
| 응답 지연 | 타임아웃 | 리소스 점유 방지 |
| 부분 기능 장애 | 폴백 | 사용자 경험 유지 |
| 리소스 고갈 | 벌크헤드 | 장애 격리 |
| 과도한 트래픽 | 속도 제한 | 시스템 보호 |
| 서비스 인스턴스 장애 | 헬스 체크 + 자동 복구 | 비정상 인스턴스 제거 및 재시작 |
| 구분 | 도구/기술 |
|---|---|
| 애플리케이션 레벨 | Resilience4j, Spring Retry, Polly(.NET) |
| 서비스 메시 | Istio, Linkerd, Envoy Proxy |
| 컨테이너 오케스트레이션 | Kubernetes (Liveness/Readiness Probe, Auto Restart) |
| 모니터링 | Prometheus + Grafana, Datadog, ELK Stack |
| 카오스 엔지니어링 | Chaos Monkey, LitmusChaos, Gremlin |