OpenSearch API에서 FastAPI 기반 Embedding API로 HTTP 요청을 보내야 하는 요구사항이 있었다. 초기 구현은 WebClient로 작성했지만, 논블로킹 이벤트-루프 모델이 반드시 필요한 시나리오는 아니었다. 따라서 동기·블로킹 방식인 RestClient로 로직을 리팩터링해 코드 가독성과 유지보수성을 높이는 것이 적절하다고 판단했다. 하여 어떤 부분이 다르고, 어떤 특징이 있는지 알아본다.
01. RestTemplate vs WebClient vs RestClient
| 항목 | RestTemplate | WebClient | RestClient |
|---|---|---|---|
| 최초 도입 | Spring 3.0 (2009) | Spring 5 (WebFlux, 2017) | Spring 6.1 (2023) |
| 스레드 모델 | 동기·블로킹 | 비동기·논블로킹 | 동기·블로킹 |
| API 스타일 | 템플릿 메서드 | 플루언트 체이닝 (Mono/Flux) | 플루언트 체이닝 |
| 유지 상태 | Maintenance mode | 적극 개발 중 | RestTemplate 대체 목적 |
| 의존 모듈 | spring-web | spring-webflux | spring-web |
| 대표 사용처 | 레거시 MVC, 호출량이 적은 서비스 | 대량 병렬 호출, 스트리밍, 리액티브 서비스 | 최신 MVC(동기) 서비스, WebClient 문법 선호 |
01-1. RestTemplate
REST Clients :: Spring Framework
WebClient is a non-blocking, reactive client to perform HTTP requests. It was introduced in 5.0 and offers an alternative to the RestTemplate, with support for synchronous, asynchronous, and streaming scenarios. WebClient supports the following: Non-blocki
docs.spring.io
// getForObject
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.example.com/user/1";
User user = restTemplate.getForObject(url, User.class);
// exchange
RestTemplate restTemplate = new RestTemplate();
String url = "https://api.example.com/user/1";
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token");
HttpEntity<Void> entity = new HttpEntity<>(headers);
ResponseEntity<User> response = restTemplate.exchange(
url,
HttpMethod.GET,
entity,
User.class
);
User user = response.getBody();
[Thread A]
1. 손님이 웨이터 A에게 메뉴 주문 (HTTP 요청)
2. 웨이터 A는 주방에 주문서를 전달하고 → 그 자리에 멈춰서 기다림
3. 요리가 다 끝날 때까지 웨이터 A는 움직이지 않음 (= 블로킹됨, Thread A 점유)
4. 요리가 완성되면 → 웨이터 A가 받아서 손님에게 가져다줌
RestTemplate은 2009년 Spring 3.0에서 제공되는 동기/블로킹 HTTP 클라이언트다. getForObject(GET 전용)이나 exchange(GET, POST, PUT, DELETE)같은 템플릿 메서드를 통해 요청을 수행하며, 내부적으로는 HttpMessageConverter를 통해 JSON/XML 등을 직렬화/역직렬화 한다. Spring 5부터는 maintenance mode로 전환되어 기능 추가나 성능 개선이 더 이상 이루어지지 않지만, MVC에서는 여전히 동작한다. 또한, restTemplate을 통해 HTTP 요청을 보내게되면 스레드(Thread)가 블로킹(Blocking) 되어서 응답을 받을때까지 스레드(Thread)를 점유하게 된다. 그렇기에 요청이 급격하게 몰리는 경우 스레드 풀(Thread Pool)이 고갈될 수 있어, 확장성이 제한된다.
01-2. WebClient
REST Clients :: Spring Framework
WebClient is a non-blocking, reactive client to perform HTTP requests. It was introduced in 5.0 and offers an alternative to the RestTemplate, with support for synchronous, asynchronous, and streaming scenarios. WebClient supports the following: Non-blocki
docs.spring.io
webClient.get()
.uri("https://api.example.com/data")
.retrieve()
.bodyToMono(String.class)
.subscribe(res -> {
// ❶ 응답이 도착한 후 실행되는 로직
System.out.println("응답: " + res);
});
// ❷ WebClient 호출 직후 실행되는 로직
System.out.println("다음 로직 실행 중...");
[Thread B]
1. 손님이 웨이터 B에게 메뉴 주문 (HTTP 요청)
2. 웨이터 B는 주문서를 주방에 넘기고 → 바로 다음 손님 응대
(Thread B는 반환됨, 스레드 풀에 다시 사용 가능)
[주방 스레드 또는 이벤트 루프]
3. 주방에서 요리가 끝나면 → 벨을 누르거나 알림이 옴 (콜백 발생)
[Thread C]
4. Thread C가 알림을 받고 → 손님에게 요리를 전달함
Spring WebClient는 2017년 Spring 5에서 제공되는 비동기/논블로킹 HTTP 클라이언트다. WebClient는 Mono, Flux 기반의 플루언트 체이닝(메서드 체이닝 + 문장처럼 읽히게) API를 제공하고, block() 함수를 호출하면 동기/블로킹 방식으로 전활할 수 있지만, 이때는 논블로킹의 이점을 잃는다. Spring 팀이 적극적으로 기능을 확장하고 있으며 기본적으로 spring-webflux 의존성이 필요하다. 내부적으로는 이벤트-루프 스레드로 네트워크 I/O를 처리하므로 요청을 보낸 스레드(Thread)가 응답을 기다리며 대기하지 않는다.
즉, WebClient를 비동기(async)로 호출하면, 요청을 보낸 스레드는 응답을 기다리지 않고 즉시 다음 로직으로 넘어간다. 서버로부터 응답이 도착하면 별도의 이벤트-루프 스레드가 이를 감지하고 후속 로직(예: subscribe 내부 로직)을 실행한다. 이러한 구조 덕분에 WebClient는 스레드를 오래 점유하지 않고도 많은 요청을 동시에 처리할 수 있다.
01-3. RestClient
REST Clients :: Spring Framework
WebClient is a non-blocking, reactive client to perform HTTP requests. It was introduced in 5.0 and offers an alternative to the RestTemplate, with support for synchronous, asynchronous, and streaming scenarios. WebClient supports the following: Non-blocki
docs.spring.io
String res = RestClient.create()
.get()
.uri("https://api.example.com/hello")
.retrieve()
.body(String.class);
Spring RestClient는 2023년 Spring 6.1에서 도입된 동기/블로킹 HTTP 클라이언트다. WebClient와 동일한 플루언트 체이닝 API(get() → retrieve() → body())를 제공하면서, spring-web 의존성이 필요하다. RestTemplate과 마찬가지로 동기 방식을 사용하기 때문에, 요청이 들어오게 되면 블로킹 방식으로 스레드(Thread)를 점유하게 된다. 그렇기 때문에, 요청이 많아지는 경우 스레드 풀 고갈이 있을 수도 있음.
99. 참고 자료
REST Clients :: Spring Framework
WebClient is a non-blocking, reactive client to perform HTTP requests. It was introduced in 5.0 and offers an alternative to the RestTemplate, with support for synchronous, asynchronous, and streaming scenarios. WebClient supports the following: Non-blocki
docs.spring.io
@Bean vs @Component
Spring으로 개발을 하다보면 @Bean과 @Component를 언제 써야할지 헷갈릴때가 있다.둘다 목적이 명확하지 않은 Bean을 생성할때 사용하는 어노테이션인데 왜 2개로 나누어져있나 궁금했었는데, 박재성
jojoldu.tistory.com
[Spring Boot] RestClient를 활용한 HTTP 요청
목차 RestClient란?Spring Framework 6.1 M2에서 새롭게 도입된 RestClient는 RestTemplate를 대체하는 동기식 HTTP 클라이언트입니다. 이 클라이언트는 HTTP 라이브러리에 대한 추상화를 제공하여 Java 객체를 HTT
tychejin.tistory.com
'Spring MVC > Spring MVC - Practice' 카테고리의 다른 글
| [Spring] Spring @Scheduled 스케줄러 (0) | 2025.01.07 |
|---|---|
| [Spring] Spring Boot JUnit5 자주 사용되는 어노테이션 정리 (0) | 2025.01.07 |