Programming/Spring

[Spring] RestTemplate의 Connection Timeout 설정과 에러 패턴

기록하는 백앤드개발자 2024. 11. 14. 07:07
반응형

ㅁ 들어가며

ㅇ 회사에서 외부API의 통신에서 에러가 발생하여 그 원인을 분석하였다.

ㅇ 외부 연동된 API는 처리하는데 1.7초, 내부적으로 Connection Timeout 설정이 1.5초로 되어 있었다.

ㅇ 이번 글에서는 Connection Timeout 설정 방법과 에러 패턴, 최적의 Timeout 설정, 에러 처리 및 로깅 방법에 대해서 정리해 보았다.

 

ㅁ Connection Timeout 설정 방법

Spring RestTemplate에서 connection timeout을 설정하는 방법은 크게 두 가지가 있다.

 

1. HttpComponentsClientHttpRequestFactory 사용

HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000); // 5초
factory.setReadTimeout(5000); // 5초

RestTemplate restTemplate = new RestTemplate(factory);

이 방법은 Apache HttpComponents 라이브러리를 사용하여 connection timeout과 read timeout을 모두 설정할 수 있다.

 

2. RestTemplateBuilder 사용 (Spring Boot)

Spring Boot 환경에서는 RestTemplateBuilder를 사용하여 더 간단하게 설정할 수 있다.

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
        return restTemplateBuilder
            .setConnectTimeout(Duration.ofSeconds(5))
            .setReadTimeout(Duration.ofSeconds(5))
            .build();
    }
}

 

ㅁ Connection Timeout 에러 패턴

Connection timeout이 발생하면 일반적으로 다음과 같은 에러 패턴이 나타난다.

 

SocketTimeoutException

java.net.SocketTimeoutException: 이 예외는 connection timeout 또는 read timeout이 발생했을 때 던져진다.

java.net.SocketTimeoutException: Connect timed out

 

ResourceAccessException

org.springframework.web.client.ResourceAccessException: RestTemplate은 일반적으로 SocketTimeoutException을 ResourceAccessException으로 감싸서 던진다.

org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://example.com": Connect timed out; nested exception is java.net.SocketTimeoutException: Connect timed out

 

ConnectException

java.net.ConnectException: 때때로 connection timeout은 ConnectException으로 나타날 수 있다.

java.net.ConnectException: Connection timed out: connect

 

ㅁ 최적의 Timeout 설정

적절한 timeout 값을 설정하는 것은 매우 중요하다. 너무 짧게 설정하면 정상적인 요청도 timeout으로 처리될 수 있고, 너무 길게 설정하면 리소스 낭비가 발생할 수 있다. 일반적으로 다음과 같은 기준을 고려할 수 있다.

 

ㅇ 네트워크 지연: 외부 API와의 통신 시 네트워크 지연을 고려해야 한다. 일반적으로 수 초 정도의 값이 적당하다.

ㅇ API 응답 시간: 호출하는 API의 평균 응답 시간을 파악하고, 이를 기반으로 timeout을 설정한다.

ㅇ 재시도 전략: timeout 발생 시 재시도 로직을 구현한다면, 첫 번째 timeout은 짧게 설정하고 재시도 시 점진적으로 늘릴 수 있다.

 

ㅁ 에러 처리 및 로깅

Connection timeout 에러를 효과적으로 처리하기 위해서는 적절한 예외 처리와 로깅이 필요하다.

try {
    ResponseEntity<String> response = restTemplate.getForEntity("http://example.com", String.class);
    // 응답 처리
} catch (ResourceAccessException e) {
    if (e.getCause() instanceof SocketTimeoutException) {
        log.error("Connection timeout occurred: {}", e.getMessage());
        // timeout 처리 로직
    } else {
        log.error("Other I/O error occurred: {}", e.getMessage());
        // 다른 I/O 에러 처리
    }
} catch (HttpClientErrorException e) {
    log.error("HTTP client error: {}", e.getMessage());
    // HTTP 클라이언트 에러 처리
} catch (HttpServerErrorException e) {
    log.error("HTTP server error: {}", e.getMessage());
    // HTTP 서버 에러 처리
}

이러한 에러 처리 로직을 통해 timeout 발생 시 적절한 대응을 할 수 있다. 예를 들어, 재시도 로직을 구현하거나 대체 API를 호출하는 등의 방법을 사용할 수 있다.

 

ㅁ 마무리

 Spring RestTemplate에서 connection timeout을 적절히 설정하는 것은 애플리케이션의 안정성과 성능을 위해 매우 중요하다. HttpComponentsClientHttpRequestFactory나 RestTemplateBuilder를 사용하여 쉽게 timeout을 설정할 수 있으며, 이를 통해 SocketTimeoutException이나 ResourceAccessException과 같은 에러를 방지할 수 있다.

 timeout 설정은 단순히 에러를 방지하는 것을 넘어 전체 시스템의 안정성과 확장성을 높인다. 또한, 적절한 예외 처리와 로깅을 통해 timeout 발생 시 효과적으로 대응할 수 있어, 최적의 timeout 설정을 유지하는 것이 중요하다.

 

ㅁ 함께 보면 좋은 사이트

[Spring] RestTemplate은 Thread Safe할까? / RestTemplate 타임아웃(Timeout), 재시도(Retry), 로깅(Logging) 설정하기

[Spring] RestTemplate 타임아웃(Timeout), 재시도(Retry), 로깅(Logging) 등 설정하기

반응형