On this page
이번 포스팅에서는 자바에서 비동기 논블로킹 방식의 HTTP 요청을 처리할 수 있는 WebClient와 리액티브 프로그래밍에 대해 알아보겠습니다. WebClient는 Spring 5부터 제공되며, 이전의 RestTemplate보다 현대적인 방법으로 웹 서비스를 호출하는 데 유용합니다. 리액티브 프로그래밍의 기본 개념부터 실제 예제까지 함께 살펴보겠습니다.
WebClient와 그 동작 원리
WebClient는 논블로킹 I/O를 사용합니다. HTTP 요청이 발생했을 때, 요청이 완료될 때까지 스레드가 블로킹되지 않고 다른 작업을 계속할 수 있음을 의미합니다. 이는 서버의 리소스 효율성을 높이고 높은 동시성을 처리하는 데 유리합니다.
WebClient 사용 예시
다음은 WebClient를 사용하여 GET 요청을 보내고 응답을 처리하는 간단한 예제입니다.
위 코드는 https://jsonplaceholder.typicode.com/posts/1
에 GET 요청을 보내고, 응답을 문자열로 받아서 출력합니다.
오래 걸리는 API 호출 시 리소스 관리
오래 걸리는 API를 호출할 때는 다음과 같은 방법을 사용할 수 있습니다:
- 타임아웃 설정: 일정 시간이 지나면 요청을 취소하는 타임아웃을 설정할 수 있습니다.
- 비동기 및 논블로킹: WebClient는 기본적으로 논블로킹 방식이기 때문에, 요청을 보낸 후 다른 작업을 계속할 수 있습니다.
- 백프레셔: 데이터를 소비하는 속도에 따라 생산하는 속도를 조절하는 메커니즘을 사용할 수 있습니다.
타임아웃 설정 예시
WebClient에서 타임아웃을 설정하는 방법은 다음과 같습니다.
이 예제에서는 요청이 5초 이내에 완료되지 않으면 타임아웃 에러를 발생시키고, 에러 발생 시 대체 동작을 정의합니다.
Mono의 개념 및 사용 예시
Mono
는 Reactor 라이브러리에서 제공하는 단일 값의 비동기 시퀀스를 나타내는 객체입니다. 이는 CompletableFuture
와 비슷하지만, Reactive Streams 사양을 준수하여 더 많은 기능과 유연성을 제공합니다.
Mono의 동작 원리
Mono
는 단일 값을 포함하거나 에러를 발생시킬 수 있는 비동기 처리의 결과를 나타냅니다. 이를 통해 비동기 작업의 결과를 처리할 수 있습니다.
Mono 사용 예시
다음은 Mono
를 사용하여 비동기 작업을 처리하는 간단한 예제입니다.
위 예제에서는 Mono
를 사용하여 동기 및 비동기 작업을 처리하고 있습니다. Mono.just
는 즉시 값을 제공하는 Mono
를 생성하고, Mono.fromSupplier
는 공급자 함수에서 값을 비동기적으로 생성하는 Mono
를 만듭니다.
WebClient와 Mono 사용 예시
다음은 WebClient와 Mono를 함께 사용하여 비동기 HTTP 요청을 처리하는 예제입니다.
이 예제에서는 WebClient를 사용하여 비동기 GET 요청을 보내고, Mono를 통해 응답을 처리합니다. 타임아웃을 30초로 설정하여 응답 시간이 긴 경우에도 적절히 처리할 수 있도록 했습니다.
리액티브 프로그래밍의 개념
리액티브 프로그래밍은 데이터 스트림과 변경 이벤트의 전파를 중심으로 하는 비동기 프로그래밍 패러다임입니다. 이는 언어와 무관한 개념으로, 다양한 언어와 프레임워크에서 사용할 수 있습니다.
리액티브 프로그래밍의 주요 원칙은 다음과 같습니다:
- 데이터 스트림: 리액티브 프로그래밍에서 모든 것이 스트림으로 표현됩니다. 예를 들어, 변수, 사용자 입력, HTTP 요청/응답 등이 스트림으로 나타납니다.
- 비동기성: 비동기적으로 데이터를 처리하며, 이를 통해 높은 성능과 응답성을 제공합니다.
- 변경 전파: 데이터가 변경되면 이를 구독하고 있는 모든 구독자에게 자동으로 변경 사항이 전달됩니다.
- 지연 실행(Lazy Evaluation): 데이터가 실제로 필요할 때까지 계산을 지연시킵니다. 이는 리소스를 효율적으로 사용할 수 있게 합니다.
리액티브 프로그래밍의 장점
- 비동기 및 논블로킹: 높은 성능과 확장성을 제공하여 많은 요청을 효율적으로 처리할 수 있습니다.
- 구성 가능성: 스트림을 연산자와 결합하여 복잡한 데이터 처리를 간단하게 표현할 수 있습니다.
- 유지 보수성: 코드의 흐름이 명확하고, 에러 처리가 용이하여 유지 보수성이 높습니다.
리액티브 프로그래밍의 단점
리액티브 프로그래밍이 혁신적이긴 하지만, 몇 가지 단점도 있습니다:
- 학습 곡선: 리액티브 프로그래밍의 개념과 API는 전통적인 동기 프로그래밍에 비해 복잡하여, 이를 이해하고 숙달하는 데 시간이 걸립니다.
- 디버깅의 어려움: 비동기 코드의 특성상 디버깅이 어려울 수 있습니다.
- 호환성 문제: 기존의 동기 코드와 리액티브 코드 간의 상호 운용성이 어려울 수 있습니다.
실제 예제: LLM 응답 스트리밍
GPT, Gemini, Claude API와 같은 LLM의 응답을 스트리밍 방식으로 처리하여 프론트엔드에서 실시간으로 표시하는 예제를 살펴보겠습니다.
백엔드: 스프링 부트
프론트엔드: HTML + 자바스크립트
이 예제에서는 스프링 부트를 사용하여 LLM 응답을 스트리밍 방식으로 처리하고, 프론트엔드에서 실시간으로 이를 표시합니다. 이렇게 하면 긴 응답 시간의 작업도 사용자에게 실시간 피드백을 제공하여 향상된 사용자 경험을 제공할 수 있습니다.
결론
리액티브 프로그래밍과 WebClient를 사용하면 비동기 논블로킹 방식으로 HTTP 요청을 처리하고, 시스템의 성능과 확장성을 높일 수 있습니다. 이번 포스팅에서는 WebClient의 기본 사용법부터 LLM 응답 스트리밍 예제까지 다루었습니다. 리액티브 프로그래밍의 장점과 단점을 이해하고, 필요에 맞게 적용해보세요!