[Spring] What - RestClient (with WebClient, RestTemplate)

하쮸·2025년 12월 30일

Error, Why, What, How

목록 보기
60/62

1. RestClient

  • Spring 6.1 버전부터는 동기식(Synchronous)방식의 HTTP 통신을 위해 RestClient라는 API가 도입 되었음.
    • 과거에는 RestTemplate 이 사용되었음.
    • WebClient라는 것도 있는데 이는 비동기(Asynchronous) 처리나 스트리밍이 필요한 경우에 사용이 권장됨.
  • RestTemplateRestClient는 내부적으로 요청 팩토리, 인터셉터, 메시지 컨버터 등 공통 인프라를 공유하고 있으며 해당 영역의 개선 사항은 두 API 모두에 적용됨.
    • 하지만 앞으로 추가되는 고급 기능은 RestClient 중심으로 제공될 예정임.
      • 즉, RestTemplate은 유지보수 하는 쪽으로 방향이 잡혔고 앞으로 추가될 고급 기능은 RestClient를 통해 제공됨.

1-1. 인스턴스(객체) 생성.

  • 인스턴스를 생성할 때는 아래와 같은 정적 팩토리 메서드를 사용함.

    • create(), create(String baseUrl) or builder()를 통해 생성할 수 있음.
  • 기존에 사용하던 RestTemplate과 동일한 설정을 그대로 가져오고 싶다면 create(RestTemplate) or builder(RestTemplate)를 사용.


1-2. 주요 메서드.

  • 응답 본문(Response Body) 처리.
    • retrieve() or exchange()를 사용.
  • 요청 본문(Request Body) 설정.
    • body(Object) 등을 통해 데이터를 보낼 수 있음.
  • get(), post(), put(), delete() 등.
    • 각 HTTP 메서드에 맞는 요청을 함.

1-3. Ex. (RestTemplate -> RestClient)

  • RestTemplate 방식의 코드와 RestClient 방식의 코드를 예시로 비교.
@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
	@GetMapping("/test")
    public ResponseEntity<Object> getTest(@RequestParam("location") String location) {
    
    			.....
                
	JsonNode vWorldjsonNode = restTemplate.getForObject(GeocoderUrl, JsonNode.class);
    
}
  • GeocoderUrl로 HTTP GET 요청을 보내서 반환된 값을 JsonNode타입으로 받겠다는 의미의 코드.
    • getForObject 대신 getForEntity() 메서드를 사용하면 ResponseEntity 타입으로 받을 수 있어서 바디(body) 뿐만 아니라 상태코드와 헤더를 같이 가져올 수 있음.
@Configuration
public class RestClientConfig {
    @Bean
    public RestClient restClient() {
        return RestClient.create();
    }
}
@GetMapping("/weather")
    public ResponseEntity<Object> getWeather(@RequestParam("location") String location) {
    
    			.....
                
	JsonNode vWorldjsonNode = restClient.get()
    									.uri(GeocoderUrl)
                                        .retrieve()
                                        .body(JsonNode.class);
    
}
  • RestClient.create(): static 메서드를 이용해서 인스턴스를 생성.

  • GeocoderUrl로 HTTP GET 요청을 보내서 반환된 값을 JsonNode타입으로 받겠다는 의미의 코드

    • get(): GET 요청을 구성.
    • uri(): 연결할 URL을 지정.
    • retrieve(): 응답 결과를 받아옴.
    • body(): 받은 응답을 원하는 타입으로 변환. (위 예제에서는 JsonNode 타입으로 받음.)
  • body() 대신 toEntity()를 사용하면 ResponseEntity 타입으로 받을 수 있어서 바디(body) 뿐만 아니라 상태코드와 헤더를 같이 가져올 수 있음.


2. RestTemplate

  • RestClient이전에 주로 사용하던 동기식 HTTP 요청 API.

2-1. 주요 메서드.

  • GET 요청.

    • getForObject(...)
      • '응답 바디(body)'만 반환.
    • getForEntity(...)
      • '응답 바디(body) + 상태 코드 + 헤더'를 포함한 ResponseEntity 반환.
  • POST 요청.

    • postForObject(...)
      • 요청으로 리소스를 생성한 후 응답 바디만 반환.
    • postForEntity(...)
      • 요청으로 리소스를 생성한 후 ResponseEntity 반환.

2-2. 블로킹(Blocking) 클라이언트.

  • RestTemplate요청당 하나의 스레드(thread-per-request) 모델을 기반으로 하는 Java 서블릿 API를 사용함.
    • 이는 웹 클라이언트가 응답을 받을 때까지 해당 스레드가 차단(Block)됨을 의미.
    • 블로킹 코드의 문제점은 각 스레드가 일정량의 메모리와 CPU를 점유한다는 점.
  • 만약 처리 속도가 느린 외부 서비스를 호출하는 요청이 대량으로 들어온다고 가정.
    • 그럼 결과를 기다리는 요청들이 점점 쌓이게 되고 애플리케이션은 이를 처리하기 위해 수많은 스레드를 생성하게 될텐데 그럴경우 스레드 풀(Thread Pool)이 고갈되거나 메모리가 부족할 수도 있음. 또한 전체적인 성능 저하를 겪게 될 수도 있음.

3. WebClient

  • 비동기(Asynchronous) 처리나 스트리밍이 필요할 시 사용이 권장됨.
    • 대규모 트래픽, 높은 동시성 환경에 적합함.

3-1. 논블로킹(Non-Blocking) 클라이언트.

  • WebClientSpring Reactive프레임워크가 제공하는 비동기식 논블로킹을 사용함.

  • RestTemplate는 HTTP 호출마다 호출한 스레드를 직접 사용하지만
    WebClient는 HTTP 호출에 대해 작업(task)을 생성함.

    • 리액티브 프레임워크는 내부적으로 이러한 작업(task)들을 큐(Queue)에 쌓아두고 적절한 응답이 준비되었을 때만 이를 실행함.
  • 결과적으로 리액티브 방식은 동기/블로킹 방식과 비교하였을 때 더 적은 수의 스레드와 리소스를 사용하면서도 더 많은 로직을 처리할 수 있음.


4. 동기/블로킹, 비동기/논블로킹 용어 차이.

구분초점핵심
동기 / 비동기순서와 결과"작업 완료 여부를 누가 신경 쓰는가? 순서가 지켜지는가?"
블로킹 / 논블로킹제어권 (Control)"작업을 계속할 수 있는가? 아니면 멈춰서 기다려야 하는가?"
  • 즉,
    동기 / 비동기전체 작업에 대한 순차적인 흐름이 유지되고 있는가? 안 되고 있는가?에 초점을 맞추고
    블로킹 / 논블로킹전체 작업을 멈춰서 기다려야하는지? 계속 해도 되는지?에 초점이 맞춰져있음.
    • Ex) 파일 읽기.
      • 블로킹: 파일을 처음부터 끝까지 다 읽을 때까지 대기해야됨.
      • 논블로킹: 파일을 읽는 도중에 다른 작업을 할 수 있음.

5. 참고.

profile
Every cloud has a silver lining.

0개의 댓글