이번 글에서는 Spring RestTemplate에 대해 알아보겠습니다.

실무에서 HttpClient(HttpComponent) 또는 HttpUrlConnection 모듈을 사용한 서버 to 서버 통신이 많이

구현되어 있는 경우를 볼 수 있는데요.

일부 시스템들이나 간혹 다른 분들의 코드를 보면 과거 Wrapper 클래스로 만들 모듈을 그대로 재사용하는 경우가

많습니다. 스프링에서 지원하는 RestTemplate으로 기능 구현하는 것이 스프링 프레임워크를 사용하는 입장에서 

좋지 않나 싶어 구조와 사용법에 대해 정리해보겠습니다.

 

Spring RestTemplate 

RestTemplate HTTP 클라이언트 라이브러리를 통해 더 높은 수준의 API를 제공합니다.

Spring 3.x 버전부터 지원했으며, Spring 5.x부터는 WebClient를 쓰기를 권장하고 있습니다.

두 라이브러리 가장 큰 차이는 블로킹과 논블로킹 차이라고 간단하게 설명할 수 있습니다.

RestTemplate 기본 설정을 사용하면 UrlConnection과 최대 5개의 커넥션 풀을 갖게 됩니다.

RestTamplate 생성 시 ClientHttpReqeustFactory 부분을 구현하여 Apache HttpComponents

을 사용할 수도 있으며, 커넥션 풀이나 커넥션, 리드 타임아웃 같은 설정들도 세팅 가능합니다.

이러한 여러 가지 편리한 기능 지원으로 개발자는 비즈니스 구현에 더 집중할 수 있는 것 같습니다.

특징

  •  HTTP 요청 후 JSON, XML, String과 같은 다양한 응답을 받을 수 있는 템플릿 지원.
  •  Blocking I/O 기반의 동기방식을 사용.
  •  Header, Contents-Type, Http Method 등 다양한 설정 지원.

 

서버 to 서버 HTTP 통신에 많이 사용하는 라이브러리

  • URLConnection
    Java.net 패키지에 포함된 라이브러리.
    간단한 HTTP 프로토콜 기반 서비스 기능 구현 시 많이 사용.
  • Apache HttpClient (HttpComponent)
    Apache 재단에서 관리하는 라이브러리로 다양하고 편리한 기능들을 지원하기 때문에
    비교적 HTTP 프로토콜 기반 서비스 기능 구현 시 사용.

 

기존 라이브러리들 사용의 문제점

URLConnection을 빈도가 높은 기능 구현 시 사용하면 커넥션 풀을 기본적을 지원하지 않기 때문에

TIME_WAIT 상태의 연결이 증가하고 어느 시점에 가면 통신 시 hang이 걸리는 케이스가 확인됩니다.

HttpClient를 사용하더라도 매번 객체를 생성/연결 종료하여 사용하는 케이스가 있는데

이렇게 사용하면 URLConnection을 이용해 구현하는 것과 크게 다를 바가 없는 케이스로 

이럴 경우에도 hang이 걸리는 케이스가 확인됩니다.

 

 

기본 설정을 사용한 예제

아래 코드는 헤더 생성, 콘텐츠, Accept 타입 설정하여 uri를 호출하는 간단한 예시입니다.

 // 헤더 객체 생성
HttpHeaders headers = new HttpHeaders();
// 헤더 값 세팅(ex. Authorization)
headers.set(headerName, headerValue); 
// 컨텐츠 타입 세팅
headers.setContentType(MediaType.APPLICATION_JSON); 
// Accept 세팅
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); 
// RestTemplate 객체 생성
RestTemplate restTemplate = new RestTemplate(); 
HttpEntity<String> entity = new HttpEntity<String>(headers); 
// 헤더, 메소드, 응답 타입 세팅하여 uri 호출
ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
// Response Body 리턴
return responseEntity.getBody();

 

위와 같이 사용할 경우

new RestTemplate()로 객체 생성하면 exchange() 메서드 호출 시 사용하는 factory를 라이브러리

코드를 추적해보면 HttpAccessor 클래스에 getRequestFactory() 메서드에 의해

requestFactory 값으로 SimpleClientHttpRequestFactory 객체를 세팅하는 것과 HttpURLConnection을 

사용하는 것을 확인 가능하고 5개의 커넥션 풀을 생성하여 기본 설정으로 사용합니다.

 

 

HttpClient 커넥션 풀 설정을 사용한 예제 

 // 헤더 객체 생성
HttpHeaders headers = new HttpHeaders();
// 헤더 값 세팅(ex. Authorization)
headers.set(headerName, headerValue); 
// 컨텐츠 타입 세팅
headers.setContentType(MediaType.APPLICATION_JSON); 
// Accept 세팅
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); 
// Httpclient 객체 및 커넥션 풀 설정
HttpClient httpClient = HttpClientBuilder.create()
.setMaxConnTotal(50)
.setMaxConnPerRoute(10)
.build();
// factory 및 timeout 설정
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient);
factory.setConnectTimeout(4000);
factory.setReadTimeout(5000);

// RestTemplate Fcatory 설정
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(factory));

// RestTemplate 객체 생성
RestTemplate restTemplate = new RestTemplate(); 
HttpEntity<String> entity = new HttpEntity<String>(headers); 
// 헤더, 메소드, 응답 타입 세팅하여 uri 호출
ResponseEntity<String> responseEntity = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
// Response Body 리턴
return responseEntity.getBody();

HttpURLConnection 대신 HttpClient(HttpComponent)를 사용하고 커넥션 풀과 Timeout 설정을 추가한 예제입니다.

이렇게 Connection을 재사용해서 이점을 얻으려면 Keep-Alive를 지원하는지 반드시 확인하고 적용해야 합니다.

그리고 잘못 값들을 설정하여 사용할 경우 이점을 얻지 못할 수 있으며, 경우에 따라 성능이 저하될 수도 있습니다.

 

 

마치며

다음 글에서는 Spring Boot에서 RestTemplate을 Configuration과 Bean 어노테이션을 사용하여

등록하고 @Autowired를 통한 재사용을 하는 방법을 확인해보겠습니다.

 

 

참고

https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#remoting

https://hc.apache.org/httpcomponents-core-4.4.x/index.html

https://perfectacle.github.io/2021/02/14/simple-client-http-request-factory-connection-pool/

'Spring Boot Framework' 카테고리의 다른 글

Spring Boot Interceptor  (0) 2022.02.18
Spring Rest Docs 와 Swagger (2)  (0) 2022.02.12
Spring Rest Docs 와 Swagger (1)  (0) 2022.02.11
Spring Boot Oauth 2.0 과 JWT Demo (5)  (0) 2022.02.08
Spring Boot Oauth 2.0 과 JWT Demo (4)  (0) 2022.02.06

+ Recent posts