REST API 구현: Spring Boot에서 RestTemplate으로 안정성 높이기-4단계 가이드

REST API 구현은 Spring Boot 개발에서 중요한 요소입니다. 이 글에서는 Spring Boot에서 RestTemplate을 사용하여 시스템 부하 시에도 안정성을 유지할 수 있는 API 구현 방법을 4단계로 설명합니다. 타임아웃재시도 로직 설정을 통해 안정성을 높이는 방법을 알아보세요.

코드 예제: Spring Boot에서 RestTemplate을 사용한 요청/응답 구현

아래는 Spring Boot 환경에서 시스템 부하가 발생할 때 안정적인 요청/응답을 처리하는 RestTemplate 설정, Dto, 서비스 계층 코드 예시입니다.

1. RestTemplate 설정

RestTemplate 설정은 API 요청의 타임아웃을 관리하고 시스템 부하를 제어하는 중요한 요소입니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectTimeout(5000); // 커넥션 타임아웃 5초
        factory.setReadTimeout(5000);    // 리드 타임아웃 5초
        return new RestTemplate(factory);
    }
}

2. DTO 설계

DTO (Data Transfer Object)를 설계하여 데이터를 구조화합니다. REST API의 요청과 응답에 필요한 정보를 정의합니다.

// 요청 DTO
public class ReqDto {
    private String name;

    // 생성자, getter, setter 추가
    public ReqDto() {}
    public ReqDto(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

// 응답 DTO
public class ResDto {
    private String message;
    private String status;

    // 생성자, getter, setter 추가
    public ResDto() {}
    public ResDto(String message, String status) {
        this.message = message;
        this.status = status;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }
}

3. 서비스 계층에 타임아웃 및 재시도 로직 적용하기

서비스 계층에서 타임아웃과 재시도 로직을 통해 안정성을 강화합니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.TimeUnit;

@Service
public class ApiService {

    private final RestTemplate restTemplate;
    private final String externalApiUrl = "https://example.com/api"; // 실제 URL로 변경 필요

    @Autowired
    public ApiService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public ResDto fetchData(ReqDto reqDto) {
        int maxRetries = 3; // 최대 재시도 횟수
        int retries = 0;

        while (retries < maxRetries) {
            try {
                // 요청 생성
                HttpEntity<ReqDto> requestEntity = new HttpEntity<>(reqDto);

                // 외부 API 호출
                ResponseEntity<ResDto> response = restTemplate.exchange(
                    externalApiUrl,
                    HttpMethod.POST,
                    requestEntity,
                    ResDto.class
                );

                // 응답이 성공적으로 도착했을 경우 리턴
                return response.getBody();
            } catch (RestClientException e) {
                retries++;
                try {
                    // 재시도 전 대기
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    throw new RuntimeException("Thread interrupted during retry delay", ie);
                }

                if (retries >= maxRetries) {
                    // 최대 재시도 횟수를 초과했을 경우 기본 응답 반환
                    return new ResDto("Service unavailable", "ERROR");
                }
            }
        }
        return new ResDto("Unknown error", "ERROR");
    }
}

4. 컨트롤러 계층으로 API 엔드포인트 구현하기

컨트롤러에서 엔드포인트를 정의하고, 클라이언트 요청을 처리합니다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class ApiController {

    private final ApiService apiService;

    @Autowired
    public ApiController(ApiService apiService) {
        this.apiService = apiService;
    }

    @PostMapping("/fetch-data")
    public ResponseEntity<ResDto> fetchData(@RequestBody ReqDto reqDto) {
        ResDto response = apiService.fetchData(reqDto);
        if ("ERROR".equals(response.getStatus())) {
            return new ResponseEntity<>(response, HttpStatus.SERVICE_UNAVAILABLE);
        }
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
}

결론

Spring Boot에서 RestTemplate을 활용하여 REST API의 안정성을 높이는 방법은 시스템 부하 시에도 중요한 요소입니다. 타임아웃 설정과 재시도 로직을 통해 견고한 API 구현이 가능하며, 이를 통해 애플리케이션의 안정성을 강화할 수 있습니다.

위로 스크롤