학습 목표
분산 환경에서 부분 장애가 전체로 퍼지는 이유를 설명할 수 있다.
타임아웃·재시도·지수 백오프를 설계할 수 있다.
Circuit breaker 상태와 bulkhead로 격리하는 방식을 설명할 수 있다.
Fallback·graceful degradation을 아키텍처 결정으로 문서화할 수 있다.
문제 상황
- Payment 500ms인데 Order thread 200개가 Payment 무한 대기 — Order 전체 멈춤
- Payment 복구 후 재시도 폭주 — Payment 다시 다운 (retry storm)
- Inventory 장애인데 Catalog까지 503 — 동기 체인 6 hop, timeout 없음
- Circuit breaker open인데 caller가 계속 호출 — breaker 의미 없음
- 알림 실패가 주문 실패 — 핵심·부가 경계 없음
- K8s pod healthy인데 thread pool 100% — liveness만 보고 ready 무시
동기·비동기·saga까지 봤다. 장애가 나도 서비스가 부분적으로 살아남게 설계하는 편이다.
1. 복원력이란
복원력(Resilience) — 장애·부하 스파이크·느린 의존성 속에서도 핵심 기능을 허용 가능 수준으로 유지.
| 실패 모드 | 증상 |
|---|---|
| Cascading failure | A down → B 대기 → B down → C… |
| Retry storm | 복구 직후 동시 재시도로 재장애 |
| Resource exhaustion | thread·connection·memory 고갈 |
| Slow dependency | latency 합산·queue buildup |
- 가용성 QA — "100% up"이 아니라 degraded도 설계 대상
- OS — blocking I/O·thread 대기; Network — TCP timeout; 여기서는 서비스 레벨 패턴
2. 타임아웃
타임아웃 — 기다림에 상한. 없으면 영원히 점유.
| 계층 | 예 |
|---|---|
| Client | HTTP client 3s |
| Service | downstream RPC 2s |
| DB | query timeout 1s |
| LB / mesh | idle·per-try timeout |

설계 원칙
- End-to-end budget — 사용자 체감 3s면 hop 나눠 할당
- Shorter downstream — 바깥 ≥ 안쪽 합 (여유 포함)
- Cancel propagation — 상위 timeout 시 하위 요청 취소 (가능하면)
- Timeout ≠ 즉시 실패 처리 — retry·fallback과 함께
# conceptual client timeouts
http:
connect_timeout: 500ms
read_timeout: 2s
downstream:
payment_rpc: 1500ms
inventory_rpc: 800ms
- 무한
RestTemplate· JDBC — 명시 timeout 없으면 사고 후보
3. 재시도
재시도 — 일시 오류(네트워크 blip, 503)에 재호출.
| 재시도 OK | 재시도 금지 |
|---|---|
| Idempotent read | non-idempotent write (중복 결제) |
| 503·connection reset | 400·401·404 (클라이언트 오류) |
| 짧은 blip | 지속 down (breaker로 전환) |
지수 백오프 + jitter
attempt 1 → wait 100ms ± jitter
attempt 2 → wait 200ms
attempt 3 → wait 400ms
max attempts 3
- Jitter — 동시 재시도 분산 (retry storm 방지)
- 멱등 키 —
Idempotency-Keyheader, DB unique constraint - Dead letter — N회 실패 → 사람·배치 (비동기 편)
4. Circuit breaker
Circuit breaker — 의존성 연속 실패 시 호출 차단 → 자원·연쇄 방지.

| 상태 | 동작 |
|---|---|
| Closed | 정상 호출, 실패 카운트 |
| Open | 즉시 fail fast (또는 fallback), probe 대기 |
| Half-open | 소수 trial — 성공 시 Closed, 실패 시 Open |
circuit_breaker:
name: payment
failure_rate_threshold: 50%
sliding_window: 10
wait_duration_in_open: 30s
permitted_calls_in_half_open: 3
fallback: degraded_checkout
- Caller·library·sidecar(mesh) 어디에 둘지 — 일관 적용
- Open 중에도 큐잉하면 thread 고갈 — fail fast가 목적
- Half-open 없으면 복구 감지 늦음
5. Bulkhead
Bulkhead(격벽) — 자원 풀 분리 — 한 의존성이 다른 풀을 고갈시키지 않음.

| bulkhead | 예 |
|---|---|
| Thread pool | payment pool 20 · catalog pool 50 |
| Connection pool | DB per service limit |
| Semaphore | 동시 downstream N |
| Pod / cell | AZ·shard blast radius |
Order service
pool A (20 threads) → Payment sync
pool B (30 threads) → Inventory sync
pool C (10 threads) → internal DB
- Payment 느림 → pool A만 포화, pool B·C는 주문 조회 가능
- MSA 7편 장애 격리 다이어그램 — 같은 bulkhead 아이디어, 이번 편은 패턴 심화
- K8s requests/limits·HPA — 프로세스 bulkhead와 맞물림
6. Fallback과 degradation
| 전략 | 예 |
|---|---|
| Cache fallback | 추천 API down → 캐시 피드 |
| Default value | 환율 실패 → 어제 rate + 배너 |
| Queue later | 알림 실패 → outbox 재전송 |
| Feature off | 리뷰 일시 비표시 |
- Fallback 비즈니스 승인 — "결제 없이 주문"은 안 됨
- 관측 — degraded 비율·breaker open 알람
7. 실무 체크리스트
| 질문 | 좋은 답 |
|---|---|
| 모든 outbound timeout? | connect + read 명시 |
| Retry 몇 번·backoff? | 문서화 + jitter |
| Write retry 멱등? | key·constraint |
| Downstream breaker? | failure rate·half-open |
| Pool 분리? | bulkhead per dependency |
| 부가 실패가 핵심 막나? | async·fallback |
| 조합 | 효과 |
|---|---|
| timeout + retry + breaker | 단계 방어 |
| bulkhead + async side effect | 핵심 path 보호 |
| breaker + fallback | 사용자 degraded 경험 |
- Chaos engineering — breaker·bulkhead 검증 (Platform 편과 연계)
- Part 4 마무리 — 분산 = 장애 전제 + 통신 + 일관성 + 복원력
8. 정리
- Timeout — 무한 대기 금지, budget 분배
- Retry — idempotent·backoff·jitter, storm 주의
- Circuit breaker — fail fast, Closed/Open/Half-open
- Bulkhead — pool 분리, 연쇄 고갈 방지
- Fallback — 비즈니스 허용 범위만
- 다음 — 데이터 저장소 선택 (Part 5)
다음에 다룰 것
- 데이터 저장소 선택
- RDB vs NoSQL, workload별 선택 기준
해당 내용은 Fundamentals of Software Architecture (Mark Richards, Neal Ford) 및 Release It! (Michael Nygard) 의 내용을 기반으로 합니다.
'소프트웨어 아키텍처' 카테고리의 다른 글
| 캐싱 전략 (0) | 2026.07.05 |
|---|---|
| 데이터 저장소 선택 (0) | 2026.07.04 |
| 동기 vs 비동기 통신 (0) | 2026.07.02 |
| CAP과 일관성 모델 (0) | 2026.07.01 |
| 분산 시스템 기초 (0) | 2026.06.30 |