SMALL

정의

RestTemplate은 Spring에서 제공하는 Http Client

REST 서비스를 호출하는 복잡한 과정을 단순한 방식으로 만들어 주는 클래스

( 기계적이고 반복적인 코드를 깔끔하게 만들 수 있도록 도와준다)

 

Http Client 종류 

RestTemplate 뿐만 아니고 다른 종류의 Http Client가 존재하는데 각각의 특징을 간단하게 알아보자.

  • RestTemplate
    • Spring 3.0에서부터 지원
    • REST API 호출 후, 응답을 받을 때까지 기다리는 동기 방식
  • AsyncRestTemplate
    • Spring 4.0에서부터 지원
    • 비동기 RestTemplate
  • WebClient
    • Spring 5.0에서부터 지원
    • 논 블록, 리엑티브 웹 클라이언트
    • 동기, 비동식 방식 모두 지원 

 

사용법(예시)

 

Bean 등록

@RequiredArgsConstructor
@Configuration
public class WebConfig {
	
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
        return restTemplateBuilder
                .requestFactory(() -> 
                    new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory())
                )
                .setConnectTimeout(Duration.ofMillis(5000)) // connection-timeout
                .setReadTimeout(Duration.ofMillis(5000)) // read-timeout
                .build();
    }
}

 

예시

@RequiredArgsConstructor
@Service
public class RestTestService {

    private final RestTemplate template;
    
    private String getLoggerFromActuator(String url) {
    
        ResponseEntity<String> response = 
            template.getForEntity(url + "/actuator/loggers", String.class);
        
        HttpStatus statusCode = response.getStatusCode();   //상태코드확인
        HttpHeaders headers = response.getHeaders();    //헤더정보확인
        String body = response.getBody();   //바디정보확인
        
        return body;
    }
}

( 각 메서드 별 자세한 예시 : https://advenoh.tistory.com/46 )

RestTemplate 메서드

출처 :&nbsp;https://advenoh.tistory.com/46

Connection Pool 사용

기본적으로 제공되는 RestTemplate는 Connection Pool을 사용하지 않는다.

원한다면 추가적인 설정이 필요하다.

Connection Pool이 존재하지 않는다면, 

RestTemplate을 호출할 때마다, TCP 소켓을 열고, 3-way hand shaking이 발생하여 성능에 문제가 될 수 있고, 

요청량이 많아지게 되면 connection을 재활용할 수 없기 때문에 응답이 지연될 수 있다.

@RequiredArgsConstructor
@Configuration
public class WebConfig {
	
    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
    
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(); 
        factory.setReadTimeout(5000); // 읽기시간초과, ms 
        factory.setConnectTimeout(3000); // 연결시간초과, ms 
        HttpClient httpClient = HttpClientBuilder.create()
                .setMaxConnTotal(100) // connection pool 적용 
                .setMaxConnPerRoute(5) 
                .build(); 
        factory.setHttpClient(httpClient); // HttpClient 세팅 
        
        return new RestTemplate(factory);
    }
}

 

추가 참고 사항

RestTemplate 내부에서는 HttpURLConnection, HttpClient 등을 사용하는데,

해당 클래스들의 대한 내용( https://amagrammer91.tistory.com/65 )

LIST
SMALL

Customizing Response 

애플리케이션을 개발하는 과정에서

응답의 헤더에 특정 값을 추가하고 싶은 경우나

응답의 특정 데이터 값을 교체하고 싶은 경우가 있을 수 있다.

 

이러한 경우에 어떻게 해야 하는지 알아보자.

 

Interface ResponseBodyAdvice + @ControllerAdvice 

ResponseBody 데이터 접근 가능( 수정 가능 ) 

 

interceptor의 경우 postHandler method를 통해 controller 호출 이후에 접근이 가능하지만,

응답 객체에 접근 불가능 ( body에 접근 불가)

@ControllerAdvice
public class TestResponseBodyAdvice implements ResponseBodyAdvice<T> {

    // Implementation
}

 

메서드 설명 

 

@ControllerAdvice
public class TestResponseBodyAdvice implements ResponseBodyAdvice<T> {

    @Override
    public boolean supports(MethodParameter returnType, 
                            Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public T beforeBodyWrite(T body, MethodParameter returnType, 
                    MediaType selectedContentType,
                    Class<? extends HttpMessageConverter<?>> selectedConverterType, 
                    ServerHttpRequest request,
                    ServerHttpResponse response) {
        
        return body;
    }
}

 

supports 

controller 작업이 끝난 response를 beforeBodyWrite 메서드에 보낼지 판단 

판단하는 기준으로는 해당 메서드의 파라미터인 controller의 returnType정보, messageConverter 정보가 있다.

 

beforeBodyWrite

controller 작업이 끝나고 어떠한 Converter를 통해 응답을 보낼지 결정된 후에 불린다.

다만, Converter를 통하지 않은 상태이다. ( 어떠한 converter를 사용할지는 정해졌지만, 아직 convert 하지는 않은 상태 )

이 메서드에서 실제 사용자가 원하는 body의 값을 교체 또는 response에 헤더 정보를 추가할 수 있다.

 

RequestBodyAdvice

ResponseBodyAdvice와 유사하게 RequestBodyAdvice interface 사용 가능

LIST
SMALL

 

기존 설정

# application.yml

# default
spring:
    profiles:
        active: test
---
spring:
    profiles: test
        include:
        - common
# 기타 설정 .. 
---
spring:
    profiles: prod
# 기타 설정 .. 
---
spring:
    profiles: dev
# 기타 설정 ..

spring.profiles 설정을 통해 어떠한 profile인지 표시 

spring.profiles.include 설정을 통해 추가적으로 포함할 profile 표시

 

2.4 버전 이후 설정

spring.profiles 설정은 duplicated 되었다

# application.yml

# default
spring:
  profiles:
    active: test
  group:
    dev: 
    - dev-t1
    - common
---
spring:
  config:
    activate:
      on-profile: test
# 기타 설정 .. 
---
spring:
  config:
    activate:
      on-profile: prod
# 기타 설정 ..       
---
spring:
  config:
    activate:
      on-profile: dev 
# 기타 설정 ..

spring.config.activate.on-profile 설정을 통해 어떠한 profile인 경우 해당 설정들이 활성화되는지 표시 

spring.profiles.group 설정을 통해 profile들을 그룹핑 

 

활성 profile 설정 

실제로 application을 실행할 때 spring.profiles.active 설정을 주어 어떠한 profile를 활성화할 것인지 정해주어야 한다.

해당 설정이 없을 시에는 default값으로 "default" profile이 실행된다.

 

위의 예시들처럼 yaml, properties file에 설정을 해주거나 

실행 시 argument로 넘겨도 된다.

java -jar myApp.jar --spring.profiles.active=dev

 

또는, 사용하는 개발 tool의 실행 argument에 설정해주면 된다.

( 이클립스의 경우 실행 프로젝트의 오른쪽 클릭 -> Run as.. -> Run Configurations ) 

 

추가적으로, 참고할만한 링크

spring-projects github에 2.4 관련 release note와 config data migration guide 

 

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes

 

GitHub - spring-projects/spring-boot: Spring Boot

Spring Boot. Contribute to spring-projects/spring-boot development by creating an account on GitHub.

github.com

 

 

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Config-Data-Migration-Guide

 

GitHub - spring-projects/spring-boot: Spring Boot

Spring Boot. Contribute to spring-projects/spring-boot development by creating an account on GitHub.

github.com

 

LIST
SMALL

설정 파일 분리 

application.yml을 사용하는 경우에는 "---"를 사용하여 설정을 분리할 수 있다.

server:
  port: 8089
spring:
  profiles:
    active:
    - test
  application:
    name: pj2
---
server:
  port: 8089
spring:
  profiles:
    active:
    - dev
  application:
    name: devPj2

 

또한, profile 단위로 설정 파일 자체를 분리할 수도 있다.

  • application-dev.yml
  • application-test.yml
  • application-{profile}.yml

각각의 파일은 spring application을 실행 시 args 등으로 넘기는 spring.profiles.active로 결정되어진다. 

java -jar myApp.jar --spring.profiles.active=dev

 

여러 개의 설정파일 

하나의 profile에서 사용되는데 여러개의 설정 파일을 로드하고 싶은 경우가 존재할 수 있다.

이러한 경우에는 어떻게 설정하는지 알아보자.

 

spring.config.location

이 설정은 spring config의 기본 설정을 재정의하여 여러 가지의 설정 파일을 로드할 수 있다.

spring config에서 default로 제공하는 값은 아래와 같다.

사용자가 spring.config.location을 정의하면 default값은 덮어써지게 된다.

 

spring.config.additional-location

이 설정은 추가적인 위치를 설정하는 것이다.

location 설정에 플러스로 더 설정하고 싶은 경우 

 

spring.config.location, spring.config.additional-location 설정은 application.yml 파일을 로드하기 전에 사용되는 설정으로 해당 파일에 설정하면 동작하지 않는다.

SystemProperties나 CommandLine Argument로 전달해야 정삭적으로 사용될 수 있다.

java -jar myApp.jar --spring.config.additional-location=optional:classpath:test.yml

 

spring.config.import

해당 설정은 spring boot 2.4 이후부터 추가된 설정으로 위에 설명한 설정들과 달리 application.yml를 통해서 추가적인 설정 파일의 위치를 설정할 수 있다. 

 

spring:
  config:
    import:
    - optional:classpath:/test.yml

 

위의 내용들에 아래 spring문서를 확인하면 더욱 자세하게 확인 할 수있다.

https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config

LIST

+ Recent posts