2025. 3. 16. 16:20ㆍSpring Microservice
🚩[Resilience4j] 폴백(Fallback) 메커니즘 제대로 이해하고 활용하기 (feat. @CircuitBreaker와 fallbackMethod 속성 활용하기)
지난 포스팅에서는 Resilience4j의 서킷 브레이커 패턴을 구현하고 설정하는 방법을 알아보았습니다. 이번에는 Resilience4j의 또 다른 강력한 기능인 폴백(Fallback) 처리에 대해 깊이 있게 살펴보겠습니다.
🔄 Fallback 패턴이란?
Fallback(폴백) 은 원격 서비스 호출이 실패하거나 예외 상황이 발생했을 때, 즉시 에러를 사용자에게 전달하는 것이 아니라 대체할 수 있는 다른 작업을 수행하여 서비스가 우아하게(gracefully) 실패하게 만드는 패턴입니다.
- 일반적으로 원격 서비스가 일시적으로 장애가 발생할 때, 대체 경로로 사용자 요청을 처리해 사용자 경험을 유지하는 데 활용됩니다.
⚙️ Resilience4j를 이용한 Fallback 구현 방법 (코드 예제)
Resilience4j에서는 폴백 구현이 매우 직관적입니다. 단 두 가지 단계로 구성됩니다:
- 메서드 위의
@CircuitBreaker
어노테이션에서fallbackMethod
속성을 사용하여 폴백 메서드 이름을 명시합니다. - 폴백 메서드를 정의하고, 같은 클래스에 위치시킵니다.
실제 코드 예시(LicenseService.java) 🔖:
// 기존 코드 일부 생략 (LicenseService.java)
// @CircuitBreaker에서 fallback 메서드 지정
@CircuitBreaker(name = "licenseService", fallbackMethod = "buildFallbackLicenseList")
public List<License> getLicensesByOrganization(String organizationId) {
return licenseRepository.findByOrganizationId(organizationId);
}
// 폴백 메서드 구현 (같은 클래스 내)
private List<License> buildFallbackLicenseList(String organizationId, Throwable t) {
List<License> fallbackList = new ArrayList<>();
// 폴백 시 사용할 더미 라이센스 정보 생성
License license = new License();
license.setLicenseId("0000000-00-00000");
license.setOrganizationId(organizationId);
license.setProductName("Sorry no licensing information currently available");
fallbackList.add(license);
return fallbackList;
}
위 코드에서 주요 포인트는 다음과 같습니다.
- 메서드 호출이 실패하거나 타임아웃이 발생하면, Resilience4j가
fallbackMethod
에 설정된 메서드(buildFallbackLicenseList
)를 호출합니다. - 폴백 메서드는 원본 메서드와 동일한 파라미터를 받아야 하며, 추가적으로
Throwable
을 받을 수도 있습니다.
🔍 위 코드의 폴백 프로세스를 좀 더 쉽게 설명하면?
위의 buildFallbackLicenseList
메서드는 서비스 장애가 발생했을 때 간단한 더미 객체를 반환하는 방식입니다.
(실제 상황이라면 다른 데이터 소스에서 데이터를 불러오거나 캐시된 정보를 반환할 수도 있습니다.)
이제 이 메서드가 정상적으로 작동하는지 실제 테스트를 통해 확인해봅시다.
🧪 Fallback 테스트 및 결과 확인하기
이전에 설명했던 것처럼, 호출이 랜덤하게 지연되어 장애 상황을 유도했습니다.
이때 Postman에서 여러 번 호출하여 지연이 발생할 경우, Resilience4j의 fallback 메서드가 호출되어 아래와 같이 사용자가 예외 대신 더미 데이터를 받게 됩니다. ✅
🖥️ 실제 Fallback 결과 예시(실제 호출 결과):
폴백 메서드에서 반환된 더미 데이터 예시:
[
{
"licenseId": "0000000-00-00000",
"organizationId": "e6a625cc-718b-48c2-ac76-1dfdff9a531e",
"productName": "Sorry no licensing information currently available"
}
]
이제는 서비스가 실패하더라도 사용자에게는 예외 메시지 대신 친절한 안내 메시지를 포함한 정상적인 응답이 전달됩니다. 🎉
🚩 Fallback을 사용할 때 반드시 주의할 점 (중요!)
Fallback이 간편하다고 해서 모든 경우에 무조건 사용하는 것이 아닙니다. 다음 두 가지 사항을 꼭 기억하세요.
📌 1. 단순 에러 로깅만 필요하다면 try-catch를 사용하세요.
단순히 에러를 로깅하는 목적이라면 Fallback보다는 기존의 try-catch 구조가 더 적합합니다. Fallback은 대체 경로(대체 데이터 제공 등)가 필요할 때만 사용합니다.
📌 2. 폴백에서 또 다른 외부 서비스를 호출할 때는 주의하세요.
폴백 메서드 내부에서 또 다른 원격 서비스를 호출하는 경우, 원본 서비스 장애가 발생할 때 이 서비스 역시 장애 상태일 가능성이 높습니다. 따라서 폴백 메서드는 가능하면 단순하고 신뢰할 수 있는 대체 처리 방식을 구현해야 합니다.
📌 실제 운영 환경에서 권장되는 Fallback 활용법 예시
✅ 다음과 같은 폴백 활용 시나리오가 있습니다.
- 원본 서비스의 데이터가 불가능하면, 미리 준비된 캐시된 데이터 사용하기
- 미리 준비된 정적인(dummy) 데이터로 응답하여 최소한의 사용자 경험 유지하기
- 메시지 큐(Message Queue)에 사용자 요청을 임시로 저장 후, 서비스 복구 이후 비동기로 처리하기
🚩 핵심 요약 정리
항목 | 설명 |
---|---|
Fallback 개념 | 원격 호출 실패 시 대체 처리 경로 실행 |
구현 방식 | @CircuitBreaker 의 fallbackMethod 속성 활용 |
주의사항 | 로깅만 할 거면 try-catch , 추가 서비스 호출은 최소화 |
폴백 메서드 위치 | 원본 메서드와 같은 클래스에 존재해야 합니다. |
🌟 결론 및 마무리
이번 글에서 Resilience4j의 Fallback 구현 방법을 깊이 있게 알아보았습니다.
서킷 브레이커와 결합하여 더욱 견고한 마이크로서비스를 구축할 수 있게 되었으리라 생각합니다. 다음 포스팅에서도 Resilience4j의 다양한 고급 사용법과 함께 돌아오겠습니다. 끝까지 읽어 주셔서 정말 감사합니다! 🙌✨
'Spring Microservice' 카테고리의 다른 글
99 퍼센타일(percentile) (0) | 2025.03.16 |
---|---|
Implementing the bulkhead pattern (1) | 2025.03.16 |
Implementing a circuit breaker (0) | 2025.03.16 |
Spring Cloud와 Resilience4j를 사용하기 위한 라이센싱 서비스 설정 (0) | 2025.03.16 |
Implementing Resilience4j (0) | 2025.03.16 |