Circuit Breaker 패턴과 장애 전파 방지 전략

조회수 44

도입

외부 API나 다른 서비스가 느려지면 내 서비스까지 같이 느려지는 경우가 많다.

문제는 실패 자체보다 장애가 연쇄적으로 퍼지는 상황이다.

이걸 막기 위한 대표 패턴이 Circuit Breaker다.

핵심 개념 설명

Circuit Breaker는 장애가 발생한 서비스로의 요청을 일시적으로 차단하는 패턴이다.

전기 차단기와 개념이 같다. 문제가 생기면 회로를 끊는다.

  • Closed: 정상 상태
  • Open: 요청 차단 상태
  • Half-Open: 일부 요청만 테스트

핵심 목적은 장애 전파 방지다. 실패하는 시스템에 계속 요청하지 않는다.

동작 원리 또는 구조

정상 상태에서는 요청이 그대로 전달된다. 실패가 누적되면 회로가 열린다.

flowchart LR A[Client Request] --> B[Circuit Breaker] B -->|Closed| C[External API] C --> D[Response] B -->|Open| E[Fail Fast]

Open 상태에서는 외부 서비스 호출 자체를 막는다.

그래서 전체 시스템이 같이 죽는 상황을 방지한다.

상태 변화 구조

Circuit Breaker는 상태 기반으로 동작한다. 실패 횟수와 시간 기준으로 변경된다.

flowchart TD A[Closed] -->|연속 실패 증가| B[Open] B -->|대기 시간 경과| C[Half Open] C -->|요청 성공| A C -->|다시 실패| B

즉 완전히 차단만 하는 것이 아니다. 복구 여부를 주기적으로 확인한다.

실무 기준 / 적용 방법

1. Timeout 먼저 설정

Circuit Breaker 이전에 반드시 timeout이 있어야 한다.

timeout이 없으면 요청이 계속 대기한다. 그러면 스레드와 커넥션이 고갈된다.

<?php

$response = $client->request('GET', $url, [
    'timeout' => 2.0
]);

실무에서는 timeout 없이 Circuit Breaker만 쓰는 경우가 많다.

이건 거의 의미가 없다. timeout이 먼저다.

2. 실패 횟수 기준 설정

일정 횟수 이상 실패하면 Open 상태로 전환한다.

기준은 서비스 특성마다 다르다. 보통 연속 실패 기준을 사용한다.


실패 5회 연속 발생
→ Circuit Open
→ 30초 동안 요청 차단

3. Fail Fast 전략

Open 상태에서는 즉시 실패를 반환한다. 기다리지 않는다.

이게 핵심이다. 빠르게 실패해서 리소스를 보호한다.

<?php

if ($circuit->isOpen()) {
    throw new ServiceUnavailableException(
        'external api unavailable'
    );
}

4. Fallback 처리

완전히 실패시키지 않고 대체 응답을 주는 경우도 많다.

예를 들어 추천 API 장애 시 기본 추천 목록을 반환할 수 있다.

flowchart LR A[Request] --> B[Circuit Breaker] B -->|API 정상| C[External API] B -->|Open 상태| D[Fallback Response]
<?php

try {
    return $recommendApi->get();
} catch (Throwable $e) {
    return $defaultRecommendations;
}

5. Retry와 함께 사용

일시적 장애는 retry로 해결 가능하다. 하지만 retry 남발은 위험하다.

실무에서는 retry + circuit breaker를 함께 쓴다.

flowchart TD A[Request] --> B[Retry] B -->|실패 반복| C[Circuit Open] C --> D[Fail Fast]

retry는 짧게, Circuit Breaker는 크게 보호하는 역할이다.

실무에서 중요한 기준

1. 장애 서비스와 함께 죽지 않기

핵심 목적은 외부 장애 격리다. 같이 느려지지 않는 것이 중요하다.

특히 결제, 인증, 메시징 API에서 필수다.

2. Open 상태 모니터링

Circuit Open 자체가 장애 신호다. 반드시 Metrics와 연결해야 한다.


circuit_breaker_open_total
external_api_timeout_total

Open 횟수가 증가하면 외부 서비스 상태를 의심해야 한다.

3. Half-Open 트래픽 제한

복구 확인 시 모든 요청을 한 번에 보내면 안 된다.

일부 요청만 테스트해야 한다. 그렇지 않으면 장애가 다시 터진다.

4. DB에는 잘 안 씀

DB는 내부 핵심 시스템이다. 완전히 차단하면 서비스 전체가 멈춘다.

보통 외부 API나 비핵심 서비스에 많이 적용한다.

자주 발생하는 문제

1. timeout 없음

요청이 계속 대기한다. 결국 서버 리소스가 고갈된다.

Circuit Breaker보다 timeout이 먼저다.

2. retry 무한 반복

장애 상황에서 retry가 폭증하면 오히려 서비스가 더 죽는다.

retry 횟수 제한이 필요하다.

3. fallback 없음

Open 상태에서 무조건 에러만 반환하면 사용자 경험이 크게 나빠진다.

가능하면 기본 응답을 준비하는 것이 좋다.

4. 상태 공유 안 됨

서버마다 개별 상태를 가지면 일관성이 깨질 수 있다.

규모가 커지면 Redis 기반 공유 상태를 사용한다.

한 줄 요약

Circuit Breaker는 장애가 발생한 서비스 호출을 일시적으로 차단해 장애 전파를 막는 패턴이며, 실무에서는 timeout·retry·fallback과 함께 사용한다.

댓글 0

  • 첫 번째 댓글을 남겨보세요.