4장. 외부 연동이 문제일 때 살펴봐야 할 것들
내부든 외부든 서비스 간 연동은 계속 증가하는 추세이며, 그만큼 신경 써야 할 품질 문제도 함께 늘고 있다. 연동에 주의를 기울이지 않으면 서비스는 심각한 장애를 겪을 수 있다.

연동된 서비스에서 장애가 전체 서비스로 멈추는 장애로 이어질 수 있다.
연동 서비스의 문제를 완전히 차단하기는 어렵다. 하지만, 그 영향을 줄이는 방법이 있다.
타임아웃
연동 서비스에 대한 타임아웃을 설정하지 않으면, 연동 서비스의 응답이 느릴 때 처리량이 급격히 떨어진다.
A 서비스는 동시에 200개의 요청을 처리할 수 있음.
A 서비스는 B 서비스를 호출함.
B 서비스에 성능 문제가 발생하여 응답 시간이 60초 이상으로 걸림.
이러한 상황에서, A 서비스에 계속해서 요청을 받게 한다면 스레드는 계속해서 B 서비스의 응답이 오기를 기다리는 상태가 되는 것이다. 따라서 적절한 타임아웃을 설정하여 타임아웃 에러가 발생하게 하는 것도 하나의 방법이다.
물론, 사용자는 에러 화면을 보게 되지만, 반응 없는 무한 대기보다 에러 화면을 보여주는 것이 더 낫다. 사용자의 입장에서 오류가 난 줄 알고 계속해서 새로고침을 유발하여 더 큰 문제를 발생시킬 수 있기 때문이다.
연결 타임아웃 / 읽기 타임아웃
연결 타임아웃(Connection Timeout)
네트워크 연결 시도 단계
연결에 시간이 오래 걸리면 대기 시간도 함께 증가
초기 설정: 3초 ~ 5초 권장
읽기 타임아웃(Read Timeout)
연결된 후 응답을 받기까지의 시간
이 과정에서도 대기 시간 문제가 발생할 수 있음.
초기 설정: 5초 ~ 30초 권장
두 타임아웃 모두 추이를 보면서 조정하는 것이 좋다. 또한, 서비스의 특성에 따라 적절하게 설정해야 한다. 예를 들어, 결제처럼 민감한 기능은 읽기 타임아웃 시간을 약간 길게 설정해서 간헐적으로 연동 시간이 길더라도 정상적으로 처리할 수 있게 하자.
재시도
외부 연동에 실패했을 때 처리 방법 중 하나는 재시도를 하는 것이다. 네트워크 동신 과정에서 간헐적으로 연결에 실패하거나 일시적으로 응답이 느려지는 경우가 있기 때문이다.
재시도 가능 조건
항상 재시도를 하는 것은 좋지 않다. 연동 API를 다시 호출해도 되는 조건인지 확인해야 한다.
예를 들어, 포인트 서비스 API를 호출해 포인트를 차감해야하는 상황을 생각해본다면, 두 번 차감이 될 수 있기 떄문이다.
재시도를 해도 되는 조건
단순 조회 기능
연결 타임아웃
멱등성(idempotent)을 가진 변경 기능
연결 타임아웃은 연동 서비스에 아직 연결되지 않은 상태라는 뜻으로, 순간적인 네트워크 문제였다면 재시돌르 통해 연결에 성공할 가능성이 있다. 하지만, 읽기 타임아웃은 이미 연동 서비스가 요청을 처리하고 있는 것이기 때문에 주의해야 한다.
또한, 상태를 변경하는 연동 API를 재시도할 때는 멱등성을 고려하자. 여기서의 멱등성은 연산을 여러 번 적용해도 결과가 달라지지 않는 성질을 말한다.
재시도 횟수와 간격
재시도 횟수는 대부분의 경우 1 ~ 2번 정도가 적당하다. 이 이상으로 실패했을 경우 다른 근본적인 문제일 가능성이 높다. 이 경우에는 다시 재시도해도 실패할 확률이 크다.
재시도 간격은 적절한 간격을 두고 진행하는 것이 좋으며, 간격을 점진적으로 늘리기도 한다. 이를 통해 연동 서버에 가해지는 부하를 일부 완화할 수 있다.
재시도 폭풍(retry storm) 안티패턴을 조심하자.
동시 요청 제한
연동 서비스가 한 번에 처리할 수 있는 요청까지만 처리하게 하는 방법이다. 외부 서비스의 TPS를 아는 상태에서 효과적으로 처리할 수 있을 것으로 보인다.
A 서비스가 요청 300개를 받음
B 서비스는 100개의 요청을 처리할 수 있음.
나머지 200개의 요청에 대해서 어떻게 대응할 것인가?
톰캣에서 어떻게 대응할까?
서킷 브레이커

누전 차단기와 비슷하게 동작
과도한 오류가 발생하면 연동을 중지시키고 바로 에러를 응답하는 구조
열림 상태가 되면 연동 요청은 수행하지 않고, 바로 에러를 응답을 리턴한다. ⇒ 빠른 실패(fail fast)
장애가 발생한 기능에 부하가 더해지는 것을 방지
불필요한 자원 낭비를 줄여 전체 서비스의 안정성 유지에 도움
일정 시간이 지난 후 반-열림 상태로 전환되며, 이 상태에서 일부 요청에 한해 연동을 시도한다.
이 상태동안 연동에 성공하면 닫힘 상태로 복귀
반대로 연동 실패시 열림 상태로 전환되어 연동 차단 유지
외부 연동과 DB 연동
DB 연동과 외부 연동을 함께 실행할 때는 오류 발생 시 트랜잭션을 어떻게 처리할지 알맞게 판단해야 한다.
외부 연동에 실패했을 때 트랜잭션 롤백
외부 연동은 성공했지만 DB 연동에 실패해 트랜잭션 롤백
외부 연동 실패, 트랜잭션 롤백
이 케이스의 경우 읽기 타임아웃이 발생해 트랜잭션을 롤백하는 경우, 외부 서비스가 실제로는 성공적으로 처리했을 가능성을 염두에 두어야 한다.
트랜잭션을 롤백했는데 외부 서비스가 실제로는 성공했을 경우
일정 주기로 두 시스템의 데이터가 일치하는지 확인하고 보정하는 방법
성공 확인 API를 호출하는 방식
외부 연동 성공, 트랜잭션 롤백
취소 API를 호출해 외부 연동을 이전 상태로 돌리는 것이 필요하다. 데이터 일관성이 중요한 서비스라면 일정 주기로 데이터가 맞는지 비교하는 프로세스를 갖추는 것이 좋다.
Last updated
Was this helpful?