상세 컨텐츠

본문 제목

RestTemplate 기본 사용법 / Response Error Handle

Spring/RestTemplate

by Chan.94 2024. 9. 23. 16:55

본문

반응형

RestTemplate란

Spring Framework에서 RESTful 웹 서비스와 통신하기 위한 동기식 클라이언트로 HTTP 요청을 쉽게 보내고 응답을 받을 수 있도록 도와주는 유틸리티 클래스다.

 

주요 기능

  • HTTP 메서드 지원
    GET, POST, PUT, DELETE 등 다양한 HTTP 메서드를 지원
  • 요청/응답 변환
    JSON, XML 등 다양한 포맷의 요청과 응답을 Java 객체로 변환하는 기능을 제공
  • 인터셉터와 필터
    요청 전후에 특정 로직을 추가할 수 있는 인터셉터를 설정할 수 있음
  • 에러 처리
    HTTP 오류 응답에 대한 처리를 위한 메커니즘을 제공
  • 타임아웃 설정
    연결 및 읽기 타임아웃을 설정할 수 있음

기본 사용법

Connection Pool

RestTemplate은 기본적으로 Connection Pooling을 지원하지 않기 때문에 RestTemplate이 기본적으로 사용하는 URLConnection 대신 apache에서 제공하는 HttpClient를 사용하면 connection pooling이 가능합니다.

 

HttpClient 의존성 추가

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.13</version>
</dependency>

 

Configuration

@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() throws Exception{
        RestTemplate restTemplate = new RestTemplate();
        
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();

        factory.setReadTimeout(5000);       // read timeout (ms)
        factory.setConnectTimeout(3000);    // connection timeout (ms)

        //Apache HttpComponents HttpClient
        CloseableHttpClient httpClient = HttpClientBuilder.create()
                                                          .setMaxConnTotal(50)        //최대 커넥션 수
                                                          .setMaxConnPerRoute(20)     //각 호스트(IP와 Port의 조합)당 커넥션 풀에 생성가능한 커넥션 수
                                                          .build();
                                    
        factory.setHttpClient(httpClient);

        restTemplate.setRequestFactory(factory);
        return restTemplate;
    }
}

 

RestTemplate Method

 

exchange

exchange() 메서드는 Spring에서 RESTful API와 통신할 때 가장 유연한 방식 중 하나로, 다양한 HTTP 메서드를 지원하며 요청과 응답에 대한 세밀한 제어를 할 수 있다.

  • HTTP 메서드의 유연한 지원
    GET, POST, PUT, DELETE, PATCH, HEAD 등의 다양한 HTTP 메서드를 지원하기에 하나의 메서드로 다양한 요청을 처리할 수 있다.
  • Request Header와 Response Body제어 가능
    HttpEntity 객체를 통해 Request Header와 Response Body를 모두 명시적으로 설정할 수 있다. 이를 통해 인증 토큰, 커스텀 헤더 등을 설정하거나 JSON, XML과 같은 다양한 형식의 데이터를 보낼 수 있다.
  • Response Header와 Response Body 확인 가능
    ResponseEntity를 반환하므로, HTTP Status, Response Header, Response Body을 모두 쉽게 접근할 수 있다.
  • Generic Type 지원
    Response Body를 명시적으로 설정할 때 기본 객체 이외에도 Custom Object도 설정할 수 있다.
URI uri = UriComponentsBuilder.fromHttpUrl("https://example.com")
                .queryParam("authkey", "xxxxxxxxxxxxxxxxxxxxxxxx")
                .queryParam("data", "test")
                .build()
                .encode()
                .toUri();

// Request Header 제어
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer token xxxxxxxxxxx");
HttpEntity<String> request = new HttpEntity<>(headers);

// HTTP 메서드 지정
// Response Body Type 지정
ResponseEntity<Member> response = restTemplate.exchange(uri, HttpMethod.POST, request, Member.class);

// Response Header와 Response Body 확인
HttpStatus responseStatus = response.getStatusCode();
HttpHeaders responseHeaders = response.getHeaders();
Member responseBody = response.getBody();

 


Response Error Handle

RestTemplate은 4xx, 5xx의 응답 코드를 받았을 때 Exception을 발생시킨다.
개발을 하다보면 4xx, 5xx의 결과 코드도 받아서 처리해야 하는 경우가 있다.

이때 처리할 수 있는 방법에 대해 정리하고자 한다.

 

RestTemplate은 기본적으로 ResponseErrorHandler interface의 구현체인 DefaultResponseErrorHandler를 사용하여 에러 처리를 하고 있다.

 

DefaultResponseErrorHandler.java

public class DefaultResponseErrorHandler implements ResponseErrorHandler {
	...
    protected boolean hasError(int unknownStatusCode) {
        HttpStatus.Series series = HttpStatus.Series.resolve(unknownStatusCode);
        return (series == HttpStatus.Series.CLIENT_ERROR || series == HttpStatus.Series.SERVER_ERROR);
    }
    ...
    protected void handleError(ClientHttpResponse response, HttpStatus statusCode) throws IOException {
        String statusText = response.getStatusText();
        HttpHeaders headers = response.getHeaders();
        byte[] body = getResponseBody(response);
        Charset charset = getCharset(response);
        String message = getErrorMessage(statusCode.value(), statusText, body, charset);

        switch (statusCode.series()) {
            case CLIENT_ERROR:
                throw HttpClientErrorException.create(message, statusCode, statusText, headers, body, charset);
            case SERVER_ERROR:
                throw HttpServerErrorException.create(message, statusCode, statusText, headers, body, charset);
            default:
                throw new UnknownHttpStatusCodeException(message, statusCode.value(), statusText, headers, body, charset);
        }
    }
    ...
}

 

statusCode.series()의 값을 확인하여 4xx, 5xx인 경우에 HttpClientErrorException을 던지는 것을 확인할 수 있다.

 

RestResponseErrorHandler.java 

public class RestTemplateErrorHandler extends DefaultResponseErrorHandler{

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        HttpStatus statusCode = HttpStatus.resolve(response.getRawStatusCode());
        
        //코드별 Custom내용 작성
        
    }
}

 

RestTemplateConfig.java

@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() throws Exception{
        RestTemplate restTemplate = new RestTemplate();
        
        ...
        
        restTemplate.setErrorHandler(new RestTemplateErrorHandler());
        return restTemplate;
    }
}

setErrorHandler() 메서드를 통해 직접 생성한 RestErrorHandler를 추가한다.

반응형

관련글 더보기

댓글 영역

>