💡 오늘 학습 키워드
- Circuit Breaker
- Resilience4j
🎯 학습 내용 정리
MSA는 서비스를 작은 단위로 분리하여 독립적으로 개발하고 배포할 수 있다는 장점이 있다. 하지만 서비스가 서로 HTTP 호출을 통해 연결되기 때문에 하나의 서비스 장애가 전체 시스템으로 전파될 가능성이 존재한다.
예를 들어 주문 서비스가 상품 서비스와 결제 서비스를 호출한다고 가정해보자. 상품 서비스가 장애가 발생했는데도 주문 서비스가 계속해서 요청을 보내면 어떻게 될까?
상품 서비스는 복구할 시간조차 없이 계속 요청을 처리하려고 시도하게 되고, 주문 서비스 역시 응답을 기다리면서 스레드가 점점 고갈된다. 결국 하나의 장애가 전체 시스템으로 확산되는 연쇄 장애(Cascading Failure) 가 발생하게 된다.
이 문제를 해결하기 위해 사용하는 패턴이 Circuit Breaker이다.
1. Circuit Breaker
Circuit Breaker는 전기 차단기에서 이름을 가져온 패턴이다. 전기 회로에서 과전류가 발생하면 차단기가 회로를 끊어 더 큰 사고를 막는다. 마이크로서비스에서도 동일한 개념을 적용한다. 외부 서비스 호출이 계속 실패한다면 더 이상 요청을 보내지 않고 일정 시간 동안 호출을 차단한다.
덕분에
- 장애 서비스에 추가 부하를 주지 않고
- 호출하는 서비스도 빠르게 실패(Fail Fast)하며
- 시스템 전체의 안정성을 유지할 수 있다.
즉, Circuit Breaker의 목적은 장애를 복구하는 것이 아니라 장애가 전파되지 않도록 막는 것이다.
다음과 같은 구조를 생각해보자.
Client
│
Order Service
│
Product Service
평상시에는 문제가 없다.
Order → Product → 정상 응답
하지만 Product Service가 장애가 발생하면 상황이 달라진다.
Order → Product
↓
Timeout
Order Service는 계속 Product Service를 호출한다.
수천 개의 요청이 동시에 들어오면
- Timeout 증가
- Thread Pool 고갈
- CPU 사용률 증가
- 응답 지연
이 반복되면서 결국 Order Service도 장애가 발생한다.
Circuit Breaker는 일정 비율 이상 실패하면
Order Service
↓
Product 호출 차단
↓
Fallback 실행
이라는 흐름으로 동작하여 장애 전파를 방지한다.
Circuit Breaker는 항상 세 가지 상태 중 하나를 가진다.
1. Closed
기본 상태이다. 모든 요청이 정상적으로 외부 서비스까지 전달된다.
Client
│
Order
│
Product
이 상태에서는 호출 성공과 실패를 계속 기록한다. 최근 호출의 실패율이 설정한 임계값을 넘으면 Open 상태로 변경된다.
예를 들어
- 최근 5번 호출
- 3번 실패
라면 실패율은 60%이다.
설정한 실패율이 50%라면 Circuit Breaker는 Open 상태가 된다.
2. Open
Open 상태에서는 외부 서비스를 아예 호출하지 않는다.
Client
│
Order
│
X
Product
호출 즉시 실패하거나 Fallback을 수행한다.
덕분에
- Thread를 낭비하지 않고
- Timeout을 기다리지 않으며
- 장애 서비스의 부담도 줄일 수 있다.
Open 상태는 영구적이지 않다. 설정한 시간이 지나면 Half Open 상태가 된다.
3. Half Open
서비스가 복구되었는지 확인하는 단계이다. 모든 요청을 보내는 것이 아니라 일부 요청만 허용한다.
Order
↓
3개의 테스트 요청
↓
성공?
모든 요청이 성공하면
Closed
로 복귀한다.
다시 실패하면
Open
으로 돌아간다.
즉,
Closed
↓
실패 증가
↓
Open
↓
대기
↓
Half Open
↓
성공 → Closed
실패 → Open
이라는 사이클을 반복한다.
Spring Boot에서는 일반적으로 Resilience4j를 사용한다. Hystrix가 더 이상 유지보수되지 않기 때문에 현재는 Resilience4j가 사실상의 표준 라이브러리이다. Resilience4j는 Circuit Breaker뿐 아니라 다양한 장애 대응 기능을 제공한다.
대표적으로
- Circuit Breaker
- Retry
- Rate Limiter
- Bulkhead
- TimeLimiter
등을 함께 사용할 수 있다.
Spring Boot 3에서는 다음 라이브러리를 사용한다.
dependencies {
implementation 'io.github.resilience4j:resilience4j-spring-boot3:2.2.0'
implementation 'org.springframework.boot:spring-boot-starter-aop'
}
AOP를 기반으로 동작하기 때문에 AOP Starter도 함께 추가해야 한다.
Resilience4j는 application.yml에서 다양한 옵션을 설정할 수 있다.
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowType: COUNT_BASED
slidingWindowSize: 5
minimumNumberOfCalls: 5
failureRateThreshold: 50
waitDurationInOpenState: 20s
permittedNumberOfCallsInHalfOpenState: 3
각 옵션의 의미는 다음과 같다.
| 설정 | 설명 |
| slidingWindowType | 호출 수 기준 또는 시간 기준으로 통계를 계산한다. |
| slidingWindowSize | 최근 몇 개의 요청을 기준으로 실패율을 계산할지 설정한다. |
| minimumNumberOfCalls | 최소 호출 수가 충족되어야 Circuit Breaker가 동작한다. |
| failureRateThreshold | 실패율이 이 값을 넘으면 Open 상태가 된다. |
| waitDurationInOpenState | Open 상태를 유지하는 시간이다. |
| permittedNumberOfCallsInHalfOpenState | Half Open 상태에서 허용할 요청 개수이다. |
예를 들어
최근 5번 호출
3번 실패
↓
실패율 60%
↓
Circuit Open
이라는 흐름으로 동작한다.
Circuit Breaker는 어노테이션 하나로 적용할 수 있다.
@Service
public class ProductService {
@CircuitBreaker(
name = "productService",
fallbackMethod = "fallback"
)
public ProductResponse getProduct(Long id) {
return productClient.getProduct(id);
}
public ProductResponse fallback(Long id, Throwable t) {
return new ProductResponse(
id,
"상품 정보를 불러올 수 없습니다."
);
}
}
외부 호출이 실패하면 자동으로 fallback() 메서드가 실행된다.
개발자는 예외 처리를 일일이 작성하지 않아도 된다.
Fallback은 장애 발생 시 대신 실행되는 메서드이다.
예를 들어, 상품 조회가 실패했을 때
상품 정보 없음
을 반환할 수도 있고
캐시 데이터 반환
을 수행할 수도 있다.
또는
잠시 후 다시 시도해주세요.
라는 메시지를 반환할 수도 있다.
즉, 사용자가 장애를 직접 경험하지 않도록 최소한의 서비스를 제공하는 것이 목적이다.
운영 환경에서는 Circuit Breaker가 얼마나 자주 열리는지 모니터링하는 것이 매우 중요하다. Resilience4j는 Micrometer와 Actuator를 통해 메트릭을 제공한다.
의존성을 추가한다.
implementation 'io.github.resilience4j:resilience4j-micrometer'
implementation 'io.micrometer:micrometer-registry-prometheus'
implementation 'org.springframework.boot:spring-boot-starter-actuator'
그리고 Actuator를 활성화한다.
management:
endpoints:
web:
exposure:
include: prometheus
이후
/actuator/prometheus
에서 Circuit Breaker 관련 메트릭을 확인할 수 있다.
Prometheus가 메트릭을 수집하고 Grafana가 이를 시각화하면 다음과 같은 정보를 한눈에 확인할 수 있다.
- 현재 Circuit Breaker 상태
- 실패율
- Open 횟수
- Half Open 진입 횟수
- 호출 성공률
이를 통해 장애를 조기에 감지하고 대응할 수 있다.
예를 들어 주문 서비스가 상품 서비스를 호출하는 상황을 생각해보자.
1단계
주문 서비스가 상품 서비스를 호출한다.
Order
↓
Product
2단계
상품 서비스 장애가 발생한다.
Order
↓
Product
↓
Timeout
3단계
최근 호출의 실패율이 50%를 초과한다.
Circuit Breaker
↓
Open
4단계
이후 요청은 Product Service를 호출하지 않는다.
Order
↓
Fallback
사용자는 빠르게 응답을 받을 수 있고, 상품 서비스는 복구 시간을 확보한다.
5단계
20초가 지나면 Half Open 상태가 된다.
Order
↓
3개의 테스트 요청
↓
Product
6단계
모든 요청이 성공하면 다시 Closed 상태가 된다.
Closed
↓
정상 호출 재개
서비스가 복구되지 않았다면 다시 Open 상태로 전환되어 동일한 과정을 반복한다.
MSA에서는 서비스 간 호출이 많아질수록 하나의 장애가 전체 시스템으로 확산될 가능성이 커진다.
Circuit Breaker는 이러한 장애 전파를 차단하는 대표적인 패턴이며, 시스템의 복원력을 높이는 핵심 기술이다. Spring Boot에서는 Resilience4j를 통해 Circuit Breaker를 손쉽게 적용할 수 있으며, Fallback을 이용해 사용자 경험을 유지하고, Prometheus와 Grafana를 활용한 모니터링으로 장애를 빠르게 감지하고 대응할 수 있다.
운영 환경에서는 Retry, TimeLimiter, Bulkhead 등과 함께 조합하여 더욱 안정적인 마이크로서비스를 구축하는 것이 일반적이다.
📚 한줄 정리
1. Circuit Breaker는 장애를 복구하는 기술이 아니라, 장애가 다른 서비스로 전파되지 않도록 차단하여 시스템 전체의 안정성을 유지하는 핵심 패턴이다.
2. Resilience4j는 외부 서비스 장애를 감지하고 장애 전파를 차단하여 시스템의 안정성과 복원력을 높이는 장애 대응 라이브러리이다.
'Bootcamp > Fundamentals' 카테고리의 다른 글
| Spring Cloud Config와 분산 추적 (0) | 2026.07.04 |
|---|---|
| API Gateway와 OAuth2 / JWT (0) | 2026.07.03 |
| Service Discovery와 Spring Cloud LoadBalancer (0) | 2026.07.01 |
| MSA와 Spring Cloud (0) | 2026.06.30 |
| MSA 요약 (0) | 2026.06.29 |