RestTemplate이란
- Spring에서 제공하는 HTTP 클라이언트 라이브러리
- REST API를 호출할 수 있음(GET, POST, PUT, DELETE 등)
thread-safe 객체로 하나만 만들어서 여러 요청에 재사용 가능(싱글턴 사용 권장)
RestTemplate을 싱글턴으로 사용해야 하는 이유
- 매번 객체 생성에 사용하는 메모리/GC 부담을 줄여 리소스를 절약
- 타임아웃, 메시지 컨버터 등을 일관되게 관리하여 설정을 공유할 수 있음
- 하나만 생성해도 동시 요청 안전하게 처리 가능(connection pool 이용)
Connection Pool
- HTTP 연결을 미리 만들어 놓고 재사용하는 풀 의미
- 요청마다 연결을 새로 열지 않고 keep-alive 상태로 재활용
- 따라서 성능 향상에 도움이 되고 TCP 핸드셰이크 비용 절감 및 서버 자원 절약 가능
RestTemplate + Connection Pool 적용 예시
@Bean
public PoolingHttpClientConnectionManager poolingConnectionManager() {
// Apache에서 제공하는 커넥션 풀 매니저로 TCP 연결을 재사용하기 위해 반드시 필요
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
// 전체 커넥션 수
connectionManager.setMaxTotal(100);
// 도메인당 커넥션 수
connectionManager.setDefaultMaxPerRoute(20);
return connectionManager;
}
@Bean
public CloseableHttpClient httpClient(PoolingHttpConnectionManager connectionManager) {
// Apache 실제 Http 클라이언트 구현체로 HTTP 요청 전송의 주체
// custom() = HttpClientBuilder 생성하는 정적 팩토리 메서드
return HttpClients.custom()
// 위에서 생성한 커넥션 풀 설정
.setConnectionManager(connectionManager)
// 유휴 커넥션 제거
.evictIdleConnection(30, TimeUnit.SECONDS)
.build();
}
@Bean
public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory(CloseableHttpClient httpClient) {
// RestTemplate이 사용할 HTTP 요청 생성기(팩토리 역할)
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
// 기본값은 대기를 무한으로 하기 때문에 타임아웃 설정
// TCP 연걸을 맺을 때까지 기다리는 최대 시간
factory.setConnectionTimeout(5000);
// 응답 바디를 읽을 때까지 기다리는 최대 시간
factory.setReadTimeout(5000);
return factory;
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate(factory);
}
RestTemplate + Connection Pool 적용 예시(xml 기반)
<!-- 1. 커넥션 풀 매니저 -->
<!-- 이 컴포넌트가 실제 HTTP 연결을 풀로 관리 -->
<bean id="httpClientConnectionManager" class="org.apache.http.impl.conn.PoolingHttpClientConnectionManager">
<property name="maxTotal" value="100"/>
<property name="defaultMaxPerRoute" value="20"/>
</bean>
<!-- 2. HttpClientBuilder 생성 -->
<!-- HttpClients.custom() 정적 메서드 호출 -->
<!-- Apache HttpClient는 빌더 패턴 기반이라 HttpClientBuilder 통해 설정을 체이닝 -->
<bean id="httpClientBuilder" class="org.apache.http.impl.client.HttpClientBuilder" factory-method="create">
<!-- factory-method="create"로 정적 메서드 호출 -->
</bean>
<!-- 3. connectionManager 주입 -->
<!-- httpClientBuilder.setConnectionManager()에 해당하며 빌더에 커넥션 풀을 주입 -->
<bean id="httpClientWithPoolBuilder" factory-bean="httpClientBuilder" factory-method="setConnectionManager">
<constructor-arg ref="httpClientConnectionManager"/>
</bean>
<!-- 4. 실제 HttpClient 생성 -->
<!-- 커넥션 풀 설정을 포함한 CloseableHttpClient 생성, 이 객체가 실제 HTTP 요청 처리 -->
<bean id="httpClient" factory-bean="httpClientWithPoolBuilder" factory-method="build" class="org.apache.http.impl.client.CloseableHttpClient"/>
<!-- 5. HttpRequestFactory 설정 -->
<!-- RestTemplate이 HTTP 요청을 만들기 위해 이 팩토리 객체를 사용하며, 이곳에서 Apache HttpClient 통해 커넥션 풀 기반 통신을 하게 됨 -->
<bean id="httpRequestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<constructor-arg ref="httpClient"/>
<property name="connectTimeout" value="5000"/>
<property name="readTimeout" value="5000"/>
</bean>
<!-- 6. RestTemplate 등록 -->
<!-- 내부적으로 HttpComponentsClienthttpRequestFactory가 실행되며 커넥션은 PoolingHttpClientConnectionManager로부터 재사용 -->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
<constructor-arg ref="httpRequestFactory"/>
</bean>
관계도 및 흐름 정리

RestTemplate은 요청을 전송하기 위해 HttpComponentsClientHttpRequestFactory 사용
HttpComponentsClientHttpRequestFactory는 내부에서 CloseableHttpClient 활용해 요청을 전송