[Japring-Study 11] spring-http-client-1

Kim yohan·2024년 8월 22일

JapringStudy

목록 보기
11/12
post-thumbnail

spring-learning-test 과제를 진행하는 마지막 주가 시작되었다!
이번주는 http-client와 auth에 대해서 배운다!

이번 과제에선 RestClient, RestTemplate 등 여러 http client들을 사용해본다!
프로젝트 진행할 때는 OpenFeign만 사용해봤는데, 이번 기회에 다른 client들을 사용해볼 수 있어서 좋았다.


RestTemplate 사용법

String fooResourceUrl = "http://localhost:8080/spring-rest/foos";

Foo foo = restTemplate.getForObject(fooResourceUrl + "/1", Foo.class);

ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);

Get 요청은 예시 코드와 같이 getForObject를 통해, 요청을 보내고 응답 받아 객체에 매핑할 수 있다.
응답의 상태코드, 헤더를 받고 싶으면, getForEntity를 사용해 ResponseEntity를 응답으로 받을 수 있다.
다른 Http 메소드들에 대한 함수도 제공한다.


exchange()

public <T> ResponseEntity<T> exchange(
    String url, 
    HttpMethod method, 
    @Nullable HttpEntity<?> requestEntity, 
    Class<T> responseType, 
    Object... uriVariables
);

ResponseEntity<String> response = restTemplate.exchange(
            "https://jsonplaceholder.typicode.com/todos/1", 
            HttpMethod.GET, 
            request, 
            String.class
);

exchange()를 사용하면, 다양한 HTTP 메소드를 지원하고, 요청과 응답을 세밀하게 제어할 수 있다!


예외 처리

@Component
public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {

    @Override
    public boolean hasError(ClientHttpResponse httpResponse) throws IOException {
        return httpResponse.getStatusCode().is5xxServerError() || 
            httpResponse.getStatusCode().is4xxClientError();
    }

    @Override
    public void handleError(ClientHttpResponse httpResponse) throws IOException {
        if (httpResponse.getStatusCode().is5xxServerError()) {
            //Handle SERVER_ERROR
            throw new HttpClientErrorException(httpResponse.getStatusCode());
        } else if (httpResponse.getStatusCode().is4xxClientError()) {
            //Handle CLIENT_ERROR
            if (httpResponse.getStatusCode() == HttpStatus.NOT_FOUND) {
                throw new NotFoundException();
            }
        }
    }
}

RestTemplate에서 예외 처리 하려면, 위와 같이 ResponseErrorHandler를 구현해준다.



RestClient 사용법

Pet pet = restClient.get()
  .uri("https://petclinic.example.com/pets/{id}", id) 
  .accept(APPLICATION_JSON) 
  .retrieve()
  .body(Pet.class)
  
ResponseEntity<String> result = restClient.get() 
  .uri("https://example.com") 
  .retrieve()
  .toEntity(String.class); 

Get 요청은 위와 같이 보낼 수 있다.
체인 방식으로 작성한다.


exchange()

Pet result = restClient.get()
  .uri("https://petclinic.example.com/pets/{id}", id)
  .accept(APPLICATION_JSON)
  .exchange((request, response) -> { 
    if (response.getStatusCode().is4xxClientError()) { 
      throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders()); 
    }
    else {
      Pet pet = convertResponse(response); 
      return pet;
    }
  });

RestClient에서도 exchange()를 통해, 요청과 응답을 세밀하게 제어할 수 있다.


예외 처리

String result = restClient.get() 
  .uri("https://example.com/this-url-does-not-exist") 
  .retrieve()
  .onStatus(HttpStatusCode::is4xxClientError, (request, response) -> { 
      throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders()); 
  })
  .body(String.class);

RestClient에서는 .onStatus를 통해, 예외처리를 할 수 있다.


Collection 반환

public List<Todo> getTodos() {
        return restClient.get()
                .uri("/todos")
                .retrieve()
                .body(new ParameterizedTypeReference<List<Todo>>(){});
}

과제에서 나온 예시인데, Collection을 매핑할 때는 ParameterizedTypeReference<>를 사용해야 했다.



Client 별 장단점

총 5개의 옵션이 있다.
1. RestTemplate
2. WebClient
3. RestClient
4. HttpInterface
5. OpenFeign

각각에 대한 개념과 장단점을 알아보자.

RestTemplate

  • Spring 3에서 도입된 동기식 HTTP 클라이언트
  • RESTful 웹 서비스와의 통신을 단순화하여 다양한 HTTP 메서드를 지원
  • JSON, XML 등 다양한 형식의 데이터를 처리할 수 있음
  • Spring 5부터는 더 이상 주요 개발이 이루어지지 않음
  • 동기식이기 때문에, 대량의 요청을 처리할 때 성능 이슈가 발생할 수 있음

WebClient

  • Spring 5에서 도입된 비동기식 HTTP 클라이언트 (동기식 처리도 가능)
  • Flux와 Mono를 사용해 비동기, 스트리밍, 리액티브 통신을 지원
  • 대량의 요청을 처리할 때 성능과 확장성 면에서 좋음

RestClient

  • Spring 6에서 도입된 최신 HTTP 클라이언트
  • 동기 및 비동기 요청을 모두 지원

HttpInterface

  • Spring 6에서 도입된 HTTP 인터페이스
  • 인터페이스 기반으로 HTTP 클라이언트를 선언적으로 사용할 수 있음

OpenFeign

  • Netflix가 만든 선언적 HTTP 클라이언트
  • 선언적인 방식, 자동화된 HTTP 요청 처리로 서비스 간 통신을 단순화 & 유연성 제공
  • Spring Cloud와의 통합이 뛰어나고, 마이크로서비스 환경에서 주로 사용됨

정리

  • 간단한 동기 요청에는 RestTemplate
  • 비동기 및 리액티브 처리에는 WebClient or RestClient
  • 마이크로서비스 환경에는 OpenFeign or HttpInterface
profile
꾸준히 성실하게

0개의 댓글