외부 호출의 대기·재시도와 장애 영향 제한
외부 시스템이 느려지면 해당 기능의 요청뿐 아니라 내부에서 사용 중인 연결과 메모리, 대기 작업도 늘 수 있습니다. 다른 기능이 같은 자원을 사용하면 영향이 함께 퍼집니다.
운영과 결제 연동에서 이런 지연을 다룰 때는 기다리는 시간과 다시 호출할 조건을 함께 봐야 했습니다. 아래에서는 당시 접한 호출 처리와, 설계 시 구분해야 할 항목을 정리합니다.
호출 대기 시간
연결을 맺는 시간과 응답을 기다리는 시간, 전체 요청의 제한을 구분해야 합니다. 재시도를 포함한 시간이 상위 요청의 제한보다 길면 호출자는 이미 실패로 판단했는데 내부 처리는 계속될 수 있습니다.
타임아웃은 호출 측의 대기를 제한하는 기준입니다. 상대 시스템의 업무 처리가 취소됐다는 뜻은 아닙니다. 특히 결제 승인·취소에서는 응답을 못 받았어도 실제 결과가 반영됐을 수 있어 이후 상태 확인이 필요했습니다.
서킷브레이커와 서비스 탐색
서킷브레이커는 실패 조건이 충족되면 일정 기간 호출을 제한하고, 이후 허용한 시험 호출의 결과에 따라 복구 여부를 판단하는 장치입니다. 시험 호출의 수와 전환 조건은 구현과 설정에 따라 달라집니다.
결제 서비스에서 사용하던 공통 HTTP 처리에는 서비스 이름으로 대상을 찾고 호출하는 부분과 실패를 상위 워커에 전달하는 부분이 있었습니다. Eureka로 인스턴스를 찾는 기능과 호출 차단 기능은 별도입니다. 서비스 탐색을 추가했다는 이유만으로 서킷브레이커가 구성되지는 않습니다.
차단 상태에서 상위 워커로 재처리 가능 오류를 전달하더라도 즉시 무한 재시도해서는 안 됩니다. 언제 다시 처리할지와 시도 한도, 최종 실패를 기록할 방법이 함께 있어야 합니다.
재시도와 결제 결과 확인
HTTP 클라이언트와 서비스, 메시지 워커가 각각 재시도하면 실제 외부 호출 횟수가 늘어날 수 있습니다. 재시도를 어느 계층이 맡는지 정하고 전체 횟수와 시간도 함께 제한해야 했습니다.
결제에서는 상태 코드만 보고 같은 요청을 다시 보낼 수 없습니다. 승인 결과를 조회할 수 있는지, 같은 요청 식별자로 중복 처리를 막는지, 이미 반영한 결과를 다시 적용하지 않는지 확인해야 합니다.
재시도 간격을 늘리고 무작위 지연을 더하는 방식은 같은 시각에 요청이 다시 몰리는 것을 줄이는 데 도움이 됩니다. 다만 안전하게 재시도할 수 있는 업무인지에 대한 판단을 대신하지는 않습니다.
호출 자원과 실패 범위
동시 호출 수나 연결·스레드 풀을 연동별로 나누면 한쪽의 지연이 공유 자원을 전부 사용하는 상황을 제한할 수 있습니다. 이것이 bulkhead 방식입니다. 비동기 클라이언트에서도 스레드 외에 연결과 대기열·메모리 한도를 봐야 합니다.
분리한 자원도 무한하지는 않습니다. 대기열이 가득 찼을 때 바로 거부할지, 나중에 처리할지, 어느 기능을 먼저 유지할지 정해야 합니다. 분리의 효과는 연동별 실패와 자원 사용량을 보며 확인해야 합니다. 하나의 풀을 나눴다는 사실만으로 다른 기능의 응답이 유지되는 것은 아닙니다.
사용자에게 보여줄 상태
배송 조회처럼 마지막 확인 값을 보여줄 수 있는 기능도 있지만 결제 결과를 임의로 성공 처리할 수는 없습니다. 실패와 처리 결과 미확정을 구분하고, 조회할 수 없는 상태가 사용자와 운영 도구에서 어떻게 보일지 맞춰야 합니다.
호출이 다시 성공하는 것과 앞서 실패하거나 대기 중인 요청이 모두 처리된 것도 다릅니다. 복구 이후에는 누락과 중복, 지연된 메시지가 남아 있는지 확인해야 합니다.
다음 글에서는 운영 비용과 시스템 구성을 정리합니다.