본문 바로가기
IT

외부 API 장애에도 우리 서비스가 죽지 않게 하는 방법

by urosie 2025. 12. 15.
반응형

외부 API가 느려지거나 일시적으로 장애가 나면, 우리 서비스도 스레드가 묶이면서 전체가 느려지거나 다운될 수 있다.
이걸 방지하기 위해 사용하는 패턴과 기술을 정리한다.


1. 문제 정의

  • 동기 호출 구조에서는 외부 호출이 느려지면 우리 서비스 스레드가 대기
  • DB 커넥션이나 스레드 풀 고갈로 서비스 전체 장애로 확산
  • 단순 try-catch는 예외만 잡고 끝 → 스레드는 여전히 묶임

2. 기본 방어책: Timeout + Fallback

타임아웃

  • 외부 호출이 오래 걸리면 강제로 중단
  • 스레드 반환 → 다른 요청 처리 가능

Fallback

  • 외부 호출 실패 시 대체 응답 제공
  • 캐시, 기본값, 빈 목록 등
  • 서비스 죽지 않고 최소 기능 유지
 
try { return callExternalApi(); } catch (Exception e) { return cachedData(); // fallback }
  • 단순 try-catch와 달리 서비스 안정성을 위한 설계
  • 실패해도 서버가 살아남는 것이 핵심

3. Circuit Breaker 패턴

개념

  • 전기 회로 차단기에서 유래
  • 외부 시스템이 반복 실패하면 호출을 아예 차단
  • 일정 시간 후 테스트 호출 → 성공 시 다시 정상 호출

상태

상태동작
Closed 정상 호출 전달
Open 외부 호출 차단, 즉시 fallback 실행
Half-Open 제한된 호출만 테스트, 성공 시 Closed, 실패 시 Open

흐름 예시

  1. 최근 10회 중 5회 실패 → Open
  2. Open 상태에서 모든 요청 → fallback
  3. 30초 후 Half-Open → 제한된 요청만 테스트
  4. 성공 → Closed, 실패 → 다시 Open

4. 실패 기준

  • 실패 횟수 (Count-based)
  • 실패율 (Percentage-based)
  • 시간 기반 연속 실패
  • 실패 판단 기준: HTTP 5xx, Timeout, Exception, 비즈니스 실패 조건 등

중요: Open 상태에서 외부 호출은 시도조차 안 하고 fallback만 실행


5. 레거시 환경에서 Circuit Breaker 없는 경우

  • 최소한 Timeout + Fallback으로 스레드 점유를 줄이고 서비스 죽음을 방지
  • Half-Open 전략이나 Open 유지 시간은 직접 구현해야 함
  • 장기 장애 시 의미 없는 반복 호출을 막기 위해 Backoff 전략 필요

6. Spring Boot에서 Circuit Breaker 적용

  • 라이브러리: Resilience4j
  • 사용 예제:
 
@CircuitBreaker(name = "externalService", fallbackMethod = "fallback") public String callExternal() { return webClient.get() .uri("/api/data") .retrieve() .bodyToMono(String.class) .block(); } public String fallback(Throwable t) { return "기본값"; }
  • 외부 호출 실패 반복 → fallback 자동 호출
  • 일정 시간 후 Half-Open → 자동 복구 확인
  • 스프링 환경이 아니더라도 순수 Java 프로젝트에서도 사용 가능

7. 정리

  • try-catch만으로는 외부 장애 전파를 막을 수 없음
  • Timeout + Fallback = 최소한의 보호 장치
  • Circuit Breaker = 장애 격리 + 자동 복구 + 연쇄 장애 방지
  • Half-Open 전략, Open 유지 시간, Backoff 전략을 적절히 설정해야 장기 장애에도 효율적

8. 면접 대비 포인트

  • 질문: “외부 API가 느려지거나 장애가 났을 때 서비스 영향 방지 방법?”
  • 답변 요약
    • Timeout + Fallback으로 스레드 묶임 최소화
    • Circuit Breaker로 반복 호출 차단, 연쇄 장애 방지
    • Half-Open 상태에서 외부 복구 확인
    • 레거시 환경에서는 직접 Open/Half-Open 전략 구현 가능
  • 경험 예시: “Spring Boot + Resilience4j 적용, 외부 결제 API 장애에도 우리 서비스 정상 동작 확인”
반응형

댓글