[Spring] 외부 API를 호출할 때 주의할 점에 대해서

2025. 9. 16. 22:12·Backend

안녕하세요.

 

사내 업무를 진행하면서 외부 API를 호출할 일이 많이 있는데요, 오늘은 외부 API를 호출할 때 주의할 점에 대해서 학습한 내용에 대해 나누고자 글을 작성하게 되었습니다.

 

부족하거나 잘못된 내용이 있을 수 있는데, 피드백을 주신다면 꼭 확인하고 더 나은 개발자로 성장하도록 하겠습니다. 🙇🏻‍♂️


1. 외부 서버에 요청을 보낼 때 Timeout을 고려하자

가장 먼저 언급할 내용은 타임아웃을 고려하는 것입니다.

 

위 이미지와 같이 타임아웃 상황이 발생한다면 연결 자체가 수립되지 않거나, 혹은 연결은 됐으나 외부 API를 호출 후 우리 서버에선 정상적으로 응답을 받을 수 없게 됩니다.

 

조금 더 자세히 타임아웃을 알아보자면, 타임아웃 발생 상황은 아래와 같이 크게 두 가지 경우로 나뉠 수 있습니다.


Case 1 : Connection Timeout

가장 먼저 Connection Timeout입니다.

 

해당 타임아웃은 3 way handshake 과정에서 발생하고, 연결 수립이 이뤄지질 않아서 발생합니다.

쉽게 상대측 서버에 문제가 있거나 네트워크의 문제 등등 어떠한 이유로 연결이 되지 않아 통신할 수 없는 경우에 발생합니다.

 


Case 2 : Read Timeout

다음으로는 Read Timeout입니다.

 

해당 타임아웃은 Connection Timeout과는 다르게 TCP 연결을 맺은 후 발생하는 타임아웃입니다.

Connection Timeout과 다르게 외부 서버와 통신을 시작했다는 것에서 주의할 점이 있습니다.

 

외부 서버를 호출하고 응답을 받지 못했지만, 실제 외부 서버에는 어떤 작업이 이뤄질 수 있다는 점입니다.

 

위 이미지를 예시로 확인해보면 다음과 같습니다.

 

(1) 우리 서버에서 외부 서버로 무엇인가 요청을 보내고,

(2)외부 서비스에선 이를 처리하고 외부 서버 DB에 Commit까지 했지만 우리 서버에선 시간이 초과되어 Read Timeout이 발생해 응답을 받지 못하는 경우

 

그렇다면 이런 경우 어떤 일이 벌어질까요?

 

Read Timeout 문제점과 간단한 해결책

외부 서버에는 정상적으로 요청 처리가 됐지만(ex. 쿠폰 발급으로 가정) 우리 서버 입장에서는 단순 Timeout으로 처리가 되지 않았다고 판단할 수 있게 됩니다.

 

그렇다면, 우리 서버에선 쿠폰이 발급되지 않았기 때문에 다시 발급 요청을 할 수 있게 됩니다. 즉 중복으로 요청을 보내고 이중 발급과 같은 문제가 생길 수 있게 됩니다.

 

이 경우 정합성이 맞지 않아 서비스 신뢰도에 문제가 생길 수 있습니다. (우리 서버 TX Commit & 외부 Fail or 반대인 경우와 같이)

 

사실 이 문제는 우리 서버에선 확인할 방법이 쉽지 않기 때문에 골치 아픈 문제라고 생각이 드는데, 일단 생각해보면 다음 방법들을 생각해볼 수 있을 것 같습니다.

 

1. 멱등키 지원을 요청하기

- 우리 서버에서 재처리를 시도하더라도, 외부 서버에서 동일한 결과를 내려줄 수 있도록 외부 서버측에서 멱등성을 지원해주는 방법입니다.

 

2. 시간을 약속하기

- 우리 서버와 외부 서버 간 시간 약속을 정해서 동일한 시간을 기준으로 작업하는 방법입니다. 예를 들어 30초라면, 30초가 지나서 통신이 끝나면 양쪽 서버 모두 이를 실패로 간주하고 없던 일로 처리하도록 하는 방법도 있을 것 같습니다.

 

3. 일정 주기로 두 시스템 데이터가 일치하는지 확인하는 방법

 


Case 3 : 요청 시에 Timeout 설정을 지정하자 (장애 전파)

타임아웃 종류와 관계 없이 요청할 때 Timeout 설정을 고려하여 지정해야 합니다.

 

장애 전파 문제와 간단한 해결책

만약 외부 서비스로 API 요청을 하는데, Timeout 설정을 하지 않았고 하필 외부 서버에 장애가 발생해서 응답 시간이 무한정 길어진다고 가정하면 우리 서비스에선 응답을 받지 못하게 됩니다.

 

더욱 최악인 건 트래픽이 집중되어 모든 스레드가 외부 API 요청에 몰리게 되면, 스레드가 모두 고갈되어 우리 서비스의 다른 API는 이용할 수 없게 됩니다.

 

즉 외부 서비스의 장애가 우리 서비스로 이어질 수 있게 되는 것입니다.

 

그럼 이를 어떻게 해결할 수 있을까요?

 

1. Timeout 시간 설정하기

- 가장 간단한 방법으로 타임아웃을 설정하여 특정 시간이 지나면 자동으로 연결을 끊어버리는 방법이 있습니다.

 

2.  Timeout 시간 설정하기 + 서킷브레이커

- 아무리 타임아웃 설정을 해도 자주 요청을 보내는 API라면 스레드가 타임아웃 시간까지 기다리고 종료하게 됩니다.

그럼 외부 서비스의 장애가 해소될 때까지 비싼 자원인 우리 서버의 스레드는 불필요하게 낭비되는 문제가 생깁니다.

따라서 자주 사용되는 API라면 서킷브레이커를 달아서 일정 시간 이후 요청을 보내고 그동안 캐싱된 데이터 혹은 다른 응답으로 대체하는 방법을 고려할 수 있습니다.

 

3. Bulkhead 방식을 고려

- 외부 API에 요청만 보내는 별도의 스레드풀 설정을 하고, 외부 API 요청할 때 해당 스레드만 이용하도록 하는 방법도 있습니다.

이런 경우 외부 API의 응답이 느려져도 메인 스레드풀의 영향은 받지 않게 됩니다.

 

 

중요한 건 외부 API를 호출할 때 지연이 되면 스레드가 점유될 수 있다는 점이고, 이럴 때 다른 요청을 처리하지 못하게 될 수 있다는 점을 기억하면 좋을 것 같습니다.


 

2. 트랜잭션 안에 외부 API 요청을 포함시키지 말자

트랜잭션 메서드 안에 트랜잭션 작업과 외부 API를 호출하는 코드가 함께 존재한다면 DB 커넥션이 오랜 시간 점유될 수 있습니다.

 

트랜잭션이 활성화된 상태에서 비교적 실행이 오래 걸리는 외부 API를 포함시키기 때문입니다.

만약 타임아웃이 발생하지 않고 지연이 된다면 그만큼 DB 커넥션도 오래 열려있기 때문에 성능적으로 문제가 될 수 있습니다.

추가적으로 TX Commit은 되었지만, 외부 API는 실패해서 외부 DB에 데이터가 적재되지 않아 정합성 문제도 생길 수도 있습니다.

 

따라서 무분별하게 트랜잭션을 사용하면서 외부 API를 호출하는 것을 지양해야 합니다.

// InvoiceFacadeService
fun issueInvoice(...) {
    // 1. 트랜잭션 서비스 실행
    invoiceTxService.update(...)
    
    // 2. 외부 API 호출
    invoiceExternalService.requestIssue(...)
    
    ...
}

---

// InvoiceTxService
@Transactional
fun update(...) {
    ...
}

---

// InvoiceExternalService
fun requestIssue(...) {
    webClient...
}

 

위 코드와 같이 Facade 패턴을 사용해서 트랜잭션 작업과 외부 API 호출을 분리하는 방법을 사용할 수 있습니다.

또한 외부 서버와의 데이터 정합성도 생각해서 개발하는 방향을 선택해야 합니다.

 


참고

- 주니어 백엔드 개발자가 반드시 알아야 할 실무 지식 - 최범균

- 카카오페이 아티클 https://tech.kakaopay.com/post/msa-transaction/

- 토스 슬래시 22 https://www.youtube.com/watch?v=v9rcKpUZw4o

저작자표시 (새창열림)

'Backend' 카테고리의 다른 글

[Spring] MySQL을 이용한 중복 발급 방지와 동시성 해결 이야기 (멱등성, 분산락)  (1) 2025.09.10
[Spring Batch] 대량 파일 마이그레이션 작업 #1 - 도입  (6) 2025.08.02
[Kafka] Kafka 개념을 훑어보고, 주의할 점에 대해서 가볍게 알아보자  (1) 2025.07.15
'Backend' 카테고리의 다른 글
  • [Spring] MySQL을 이용한 중복 발급 방지와 동시성 해결 이야기 (멱등성, 분산락)
  • [Spring Batch] 대량 파일 마이그레이션 작업 #1 - 도입
  • [Kafka] Kafka 개념을 훑어보고, 주의할 점에 대해서 가볍게 알아보자
sosow0212
sosow0212
함께 성장하는 개발자가 되기 위해서 노력합니다.
  • sosow0212
    기록잡화점
    sosow0212
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 개발 일기
      • Backend
      • AI Engineering
  • 블로그 메뉴

    • 2025년 이전 기술블로그
    • 홈
    • 글쓰기
    • 태그
    • 방명록
  • 링크

    • 25년도 이전 개발블로그
    • LinkedIn
    • Github
  • 공지사항

  • 인기 글

  • 태그

    mysql
    Spring Batch
    spring
    마이그레이션
    backend
    분산락
    락
    멱등키
    멱등성
    Kafka
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
sosow0212
[Spring] 외부 API를 호출할 때 주의할 점에 대해서
상단으로

티스토리툴바