이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- Fallback과 Degradation은 가짜 성공과 어떻게 다른가?
- 어떤 데이터는 stale fallback이 가능하고, 어떤 데이터는 실패를 명확히 반환해야 하는가?
- 축소 응답이 성능, 정합성, 장애 격리, 운영 복잡도를 어떻게 바꾸는가?
개요
Fallback은 실패를 숨겨 성공처럼 보이게 만드는 기술이 아니다. 핵심 기능을 살리기 위해 부가 기능을 축소하고, 그 상태를 사용자와 운영자가 이해할 수 있게 드러내는 API 계약이다.
배송 위치를 못 가져올 때 주문 상세 전체를 500으로 만드는 것은 과하다. 하지만 배송 상태를 “배송 완료”처럼 꾸며서 반환하면 더 위험하다. 올바른 fallback은 “주문은 정상이고 배송 추적만 잠시 불가”를 표현한다.
Fallback의 종류
| 종류 | 예시 | 주의점 |
|---|---|---|
| 캐시 fallback | 최근 배송 위치 표시 | 데이터가 오래되었음을 표시 |
| 부분 응답 | 주문 정보만 반환 | 누락된 필드를 명확히 표현 |
| 기본값 | 추천 상품 빈 목록 | 기본값이 잘못된 판단을 만들지 않아야 함 |
| 기능 숨김 | 추천 영역 제거 | UX가 급격히 깨지지 않아야 함 |
| pending | 후속 처리 중 표시 | 상태 조회 경로 필요 |
| 명확한 실패 | 결제 승인 실패 | 재시도와 idempotency 필요 |
Fallback 선택은 데이터의 정합성 위험과 사용자 행동에 따라 달라진다.
적용하면 안 되는 곳
모든 실패에 fallback을 넣으면 위험하다.
Fallback이 부적합한 경우:
- 결제 승인 결과를 모르는 상태에서 성공처럼 보여준다.
- 재고 차감 실패를 숨기고 주문 성공을 반환한다.
- 권한 확인 실패 시 기본 허용으로 처리한다.
- 신원 인증 실패를 캐시된 성공으로 대체한다.
이 경우에는 빠른 실패와 명확한 재시도 계약이 낫다. 장애 격리는 정합성을 속여도 된다는 뜻이 아니다.
배송 조회 응답 예시
{
"orderId": "ord-1001",
"orderStatus": "PAID",
"shipping": {
"status": "TEMPORARILY_UNAVAILABLE",
"message": "배송 추적 정보를 잠시 불러올 수 없습니다.",
"source": "fallback",
"lastKnownAt": "2026-07-01T09:30:00+09:00"
}
}이 응답은 주문 상태와 배송 추적 상태를 분리한다. 사용자는 주문이 실패한 것이 아니라 배송 추적 정보만 축소되었다고 이해할 수 있다.
Degradation 단계
Degradation은 단계적으로 설계한다.
Level 0: 정상 응답
Level 1: 느린 부가 정보 제거
Level 2: 캐시된 부가 정보만 표시
Level 3: 핵심 정보만 표시
Level 4: 쓰기 차단, 읽기만 허용장애 중 어떤 단계로 갈지 미리 정해야 한다. 즉흥적으로 기능을 끄면 사용자 안내, 고객센터, 운영 지표가 따라오지 못한다.
성능과 정합성
Fallback은 성능을 보호하지만 정합성 표현을 바꾼다.
- 캐시 fallback은 빠르지만 stale data를 보여줄 수 있다.
- 기본값 fallback은 빠르지만 사용자가 기능이 없다고 오해할 수 있다.
- 부분 응답은 핵심 경로를 살리지만 클라이언트가 null과 unavailable을 구분해야 한다.
- 명확한 실패는 정합성은 지키지만 사용자 성공률이 낮아질 수 있다.
따라서 fallback 필드에는 데이터 출처와 최신성 정보가 필요할 수 있다.
클라이언트 계약
클라이언트는 fallback 상태를 정상 데이터와 구분해야 한다.
{
"field": "shipping",
"status": "DEGRADED",
"retryable": true,
"retryAfterSeconds": 60
}모바일 앱은 이 정보를 보고 배송 영역만 재조회할 수 있다. 웹은 배송 영역에만 안내 문구를 띄울 수 있다.
운영 지표
Fallback은 성공률 통계에서 분리해야 한다.
HTTP 200 success = 98%
fallback response = 22%
shipping provider error = 35%
user complaint = 증가HTTP 200만 보면 정상처럼 보인다. fallback rate가 높으면 사용자는 축소된 서비스를 쓰고 있는 것이다.
Fallback Source
Fallback의 출처를 구분한다.
| source | 의미 |
|---|---|
| cache | 최근 성공 값을 사용 |
| default | 안전한 기본값 사용 |
| hidden | 기능 영역 숨김 |
| unavailable | 대체 불가, 명확한 실패 |
운영자는 source별 비율을 보고 어떤 fallback이 자주 쓰이는지 알아야 한다.
위험 신호
- fallback 응답이 정상 응답과 구분되지 않는다.
- 결제, 재고, 권한 같은 강한 정합성 경로에 캐시 fallback을 쓴다.
- HTTP 200 비율만 보고 fallback rate를 보지 않는다.
- 클라이언트가 degraded 상태를 렌더링할 수 없다.
- fallback이 오래된 데이터를 무기한 반환한다.
- 장애가 복구되어도 fallback cache가 계속 남는다.
개인 프로젝트 기준
- fallback 가능한 필드와 불가능한 필드를 표로 나눈다.
- fallback 응답에
source나degraded를 넣는다. - 캐시 fallback을 쓰면
lastUpdatedAt을 표시한다. - fallback rate를 로그로 남긴다.
기업 운영 기준
- degradation level과 전환 조건을 runbook에 둔다.
- 고객센터와 status page가 같은 축소 상태를 설명할 수 있게 한다.
- fallback rate, stale age, user impact를 SLO와 연결한다.
- 기능 축소 상태에서 매출, 주문, support ticket 변화를 본다.
확인 질문
확인 질문
- 확인 질문: Fallback이 가짜 성공이 되지 않으려면 무엇을 드러내야 하는가?
- 답변: 어떤 데이터가 축소되었고, 출처가 무엇이며, 얼마나 오래된 값인지 또는 재시도가 가능한지 드러내야 한다.
- 확인 질문: 결제 승인에 캐시 fallback을 쓰면 안 되는 이유는 무엇인가?
- 답변: 사용자가 금전 상태를 잘못 믿게 되어 중복 결제나 잘못된 주문 상태 같은 정합성 문제가 생길 수 있기 때문이다.
- 확인 질문: HTTP 200 성공률과 fallback rate를 분리해야 하는 이유는 무엇인가?
- 답변: 200 응답이어도 사용자는 축소된 기능을 보고 있을 수 있으므로 실제 사용자 영향이 숨겨지기 때문이다.