Skip to content

외부 API 사용 시 선택할 수 있는 전략 ‐ 카카오 API 사례 기반

Myeongha Joo edited this page Jun 9, 2025 · 2 revisions

외부 API 호출 전략 단계별 선택

외부 API를 호출할 때, 서비스 상황과 성능 요구에 따라 다양한 호출 전략을 선택할 수 있습니다.

해당 글은 처리량을 테스트하기 위함이기 때문에 코드는 첨부하지 않겠습니다.

단계 전략 특징
1단계 RestClient (동기) 간단한 호출, 블록킹 I/O, 처리량 낮음
2단계 RestClient + 비동기 (ex. CompletableFuture) 병렬 처리 가능, 하지만 RestClient 내부는 블록킹이므로 한계 존재
3단계 WebClient (Reactive) 비동기 논블로킹 I/O, 고성능 가능, 적절한 리액티브 설계 필요

동기적인 프로그래밍을 시작으로 사용량에 따라 점차 비동기 논블로킹 I/O로 전환하면 현재 서버의 리소스를 최대한 활용할 수 있습니다.

처음부터 WebClient를 사용하는 것도 좋은 방법이지만, 오버 엔지니어링이 될 수 있는 것 같습니다.

간단한 비동기 동작 과정

스프링에서 비동기 프로그래밍을 하는 경우에 Blocking I/O와 Non Blocking I/O가 있습니다.

RestClient + 비동기

RestClient + 비동기

정말 심플하게 이해를 돕기 위해 그렸습니다...ㅎㅎ

  • 메인 Thread인 Tomcat Thread가 Blocking 되는 것을 막기 위해 내부의 Thread pool를 설정하여 해로운 스레드로 작업을 위임합니다.
  • 그렇기때문에 Tomcat Thread는 다른 Request를 받아서 처리할 수 있게 됩니다.
  • 대신 내부 스레드는 Blocking되어 있습니다.

WebClient (Reactive)

WebClient

출처: LG유플러스기술 블로그

  • WebClient는 I/O 작업을 커널에게 위임합니다.
  • 커널은 파일 디스크립터로 소켓 상태를 관리합니다.
  • 소켓을 읽을 수 있는 상태가 되면 이벤트를 발생시켜 이벤트 루프가 처리하도록 합니다. 때문에 Thread Blocking없이 동작이 가능합니다.

처리량 최적화 테스트 (카카오 API 사례)

이번 테스트에서는 카카오 로컬 API 를 비동기 논블로킹 I/O인 WebClient로 호출하는 경우와 RestClient(동기)로 호출하는 경우 2단계만 테스트를 진행하였습니다.

  • 테스트 도구: JMeter
  • 테스트 대상: https://dapi.kakao.com/v2/local/search/keyword.json
  • 테스트 환경: Tomcat Thread를 1개로 고정
  • WebClient + Retry 적용: 카카오 api 쿼터제로 인해 예외가 발생하여 Retry를 적용하였습니다.
전략 / 조건 처리량 (Throughput) 에러율
RestClient + 기본 처리 21 req/sec 0%
WebClient + Retry 264 req/sec 30.37% (429 Too Many Requests 발생)

RestClient 결과 RestClient

WebClient 결과 WebClient

결과 해석

  • WebClient으로 처리한 경우 Throughput이 10배정도 차이나는 것을 볼 수 있습니다.
  • 심지어 위 결과는 카카오 API의 초당 쿼터 제한이 존재하여 일정 이상부터 429(Too Many Requests) 발생 → Retry/Backoff 영향으로 Throughput이 감소한 상태였습니다.
  • 정상 상황(쿼터 제한이 없다면)에서는 WebClient가 지금보다 훨씬 더 높은 처리량을 낼 수 있다고 생각합니다.
    • 이번 결과는 API 제공자의 쿼터 정책 영향이 컸던 것

결론

  • WebClient 자체는 서버 리소스를 효율적으로 사용하는 구조이므로 스레드 풀 고갈 없이 많은 요청 처리가 가능합니다.
  • WebClient 기반 구조는 충분히 높은 처리량을 낼 수 있지만 API 제공자의 쿼터 제한이 있는 경우에는 별도의 Retry/Backoff 설계가 중요합니다.

그 외 전략

  • Java Virtual Thread: 커널 수준의 Thread가 아니기 때문에 매우 가볍다는 특징이 있습니다.
  • Kotlin: Kotlin의 코루틴은 비동기 처리를 위한 경량화된 실행 단위이며, Thread 단위가 아니라 여러 코루틴이 하나의 Thread 위에서 협력적으로 실행됩니다. 이를 통해 Thread blocking 없이 효율적인 리소스 사용이 가능합니다.
Clone this wiki locally