컨텐츠로 건너뛰기
목차
1. 외부 서비스 연동
1. 타임아웃과 재시도
1) 타임아웃 (Timeout)
- 연동된 외부 서비스에 대해 타임아웃을 설정하지 않으면, 내 서버의 상태와 상관없이 처리량이 급격히 떨어질 수 있음.
- 타임아웃 종류:
- 연결 타임아웃 (Connection Timeout): 외부 서비스와 네트워크 연결을 시도하는 단계에서 기다릴 수 있는 최대 시간. (권장: 3~5초)
- 읽기 타임아웃 (Read Timeout): 연결된 외부 서비스에 요청을 전송하고 응답을 받을 때 기다릴 수 있는 최대 시간. (권장: 5~30초)
- 읽기 타임아웃이 긴 이유: 결제 서비스 등에서 응답이 늦게 올 경우, 내 서버에선 타임아웃으로 실패 처리했지만 외부 서비스에선 성공 처리되는 데이터 불일치 문제를 최소화하기 위함임.
- 주의사항 (소켓 타임아웃): 패킷 하나하나에 대한 응답 시간이므로, 전체 응답 시간과는 다를 수 있음.
2) 재시도 (Retry)
- 외부 연동 실패 시 재시도 처리를 할 수 있지만, 상황에 따라 주의해서 사용해야 함.
- 재시도 권장 상황:
- 단순 조회 기능일 때.
- 연결 타임아웃이 발생했을 때 (아직 요청이 전달되지 않음).
- 멱등성(Idempotence)이 보장된 변경 기능일 때.
- 재시도 금지 상황: 검증 오류(4xx) 등 재시도해도 실패가 확정적인 경우.
2. 재시도 횟수와 간격
- 연동 서비스가 과부하 상태일 때 무분별한 재시도는 상황을 악화시킴.
- 재시도 횟수: 1~2번이면 충분함. (총 3번 시도해도 안 되면 일시적 오류가 아닐 확률이 높음)
- 재시도 간격: 네트워크 단절 등 특정 시간 동안 복구가 안 될 경우를 대비해, 간격을 점차 늘려가며 보내는 방식(Exponential Backoff) 등을 고려해야 함.
2. 동시 요청 제한
1. 동시 요청 제한 (Bulkhead Pattern)
- 연동 서비스가 처리할 수 있는 용량에 맞춰 내 서버에서 보내는 동시 요청 수를 제한해야 함.
- 내 서버 트래픽이 300이어도 연동 서비스가 100만 처리가능하다면, 나머지 200은 대기하거나 실패 처리하여 연동 서비스의 장애를 방지해야 함.
- 이를 통해 특정 기능의 장애가 전체 시스템으로 전파되는 것을 막을 수 있음.
2. 서킷 브레이커 (Circuit Breaker)
- 연동 서비스가 장애 상태일 때 계속 요청을 보내는 것은 리소스 낭비임.
- 장애가 감지되면 즉시 에러를 반환하는 빠른 실패(Fail Fast)를 유도하여 시스템 전체의 안정성을 확보함.
- 일정 시간 후 다시 요청을 보내보고, 정상화되었으면 차단을 해제하는 방식으로 동작함.
3. 외부 연동과 DB처리
1. 트랜잭션 처리
- 하나의 트랜잭션 내에서 외부 연동과 DB 처리가 섞여 있을 때, 실패 케이스별로 대응 전략이 필요함.
- 외부 연동 실패 시:
- 연결 타임아웃: 요청 자체가 안 갔으므로 트랜잭션 롤백하면 됨.
- 읽기 타임아웃: 외부 서비스는 성공했을 수 있음. 데이터 정합성을 위해 주기적 대사(Batch)나 성공 확인 API 호출이 필요함.
- 외부 연동 성공, DB 처리 실패 시:
- 외부 서비스에는 데이터가 반영되었으므로, 반드시 취소 API(보상 트랜잭션)를 호출해 상태를 되돌려야 함.
- 취소마저 실패할 수 있으므로 주기적인 데이터 검증 프로세스가 필수적임.
2. DB 커넥션 풀
- DB 트랜잭션 범위 안에서 외부 연동을 수행하면, 외부 서비스 응답이 늦어질 때 DB 커넥션을 계속 점유하게 됨.
- 이로 인해 DB 부하와 상관없이 커넥션 풀 고갈(Exhaustion)이 발생하여 전체 서비스 장애로 이어질 수 있음.
- 해결: 외부 연동은 DB 트랜잭션 범위 밖에서 수행해야 함. 단, 이 경우 실패 시 롤백 처리에 대한 명확한 정책이 필요함.
4. HTTP 커넥션 풀
- DB 커넥션 풀과 마찬가지로, 브라우저 단에서 서버 측으로 HTTP 연결을 맺을 때 커넥션 풀을 생성하여 연결을 재사용할 수 있음.
- 고려 사항:
- HTTP 커넥션 풀 크기: 서버 성능이 받쳐주는 수준 하에서 적절한 크기를 선택해야 함. 무턱대고 늘리면 서버 부하로 전체 응답 시간이 저하될 수 있음.
- 커넥션 대기 시간: 풀 크기가 3이고 요청이 4개라면, 남은 요청이 커넥션을 얻기 위해 얼마나 기다릴지 결정해야 함. (보통 1~5초 권장)
- Keep-Alive: 한 번 맺은 HTTP 커넥션을 일정 시간 유지하여 불필요한 핸드쉐이크 비용을 줄여야 함.