728x90
반응형
SMALL
스트링 REST Client
스프링 부트가 REST 클라이언트 관련해서 직접적으로 기능을 제공하는 것은 아니다. REST 클라이언트는 Spring Framework에서 제공하는 것이고, 부트는 그걸 쉽게 사용할 수 있도록 빈을 등록해준다.
주의 할 것은 RestTemplate과 WebClient 두 타입의 빈을 등록해주는 것이 아니라, 빌더를 등록해준다. 그래서 우리는 빌더를 주입받아서 필요할 때마다 REST 클라이언트를 빌드해서 사용해야한다.
RESTful 웹 서비스를 소비하는 데 사용할 수 있는 몇 가지 방법이 있습니다. 주로 사용되는 두 가지 주요 도구는 **RestTemplate**과 **WebClient**이다.
1. RestTemplate:
- 이것은 Spring이 제공하는 동기식 HTTP 클라이언트이다.
- RESTful 서비스를 호출하는 데 사용되며, HTTP 메서드에 대한 템플릿 메서드를 제공한다.
- 예를 들어, GET, POST, PUT, DELETE 등의 메서드를 지원한다.
- 그러나 Spring 5.0 이후로는 RestTemplate이 deprecated되었으며, 대신 WebClient를 사용하는 것이 권장된다.
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);
- Blocking I/O 기반의 Synchronous API
- RestTemplateAutoConfiguration
- 프로젝트에 spring-web 모듈이 있다면 RestTemplateBuilder를 빈으로 등록
예제로 이해하기
1) @RestController 구현
- 3초를 sleep하는 GetMapping
- 5초를 sleep하는 GetMapping
2) REST Client요청은 ApplicationRunner 구현 클래스에서 보내보자
@RestController
public class SampleController {
@GetMapping("/hello")
public String hello() throws InterruptedException {
Thread.sleep(3000L);
return "hello";
}
@GetMapping("/sample")
public String sample() throws InterruptedException {
Thread.sleep(5000L);
return "sample";
}
}
방법1. RestTemplateBuilder를 주입받아 RestTemplate 생성
- getForObject로 get요청 보내기
- blocking i/o : 호출된 함수가 자신의 작업을 모두 마칠 때까지 호출한 함수에게 제어권을 넘겨주지 않고 대기하게 만듬
- sync : 호출된 함수의 작업 완료 여부를 신경쓰기 때문에 작업을 마칠 때까지 기다린다.
@Component
public class RestRunner implements ApplicationRunner {
@Autowired
public RestTemplateBuilder restTemplateBuilder;
@Override
public void run(ApplicationArguments args) throws Exception {
RestTemplate restTemplate = restTemplateBuilder.build();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
String helloResult = restTemplate.getForObject("<http://localhost:8080/hello>", String.class);
String sampleResult = restTemplate.getForObject("<http://localhost:8080/sample>", String.class);
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}
}
해당 코드의 결과
- 5초 째에 "hello"를 출력하고, 8초 째에 "sample"을 출력한다.
- sync-blocking : /hello GET요청이 끝날 때까지 기다리고, /sample GET요청이 끝날 때까지 기다림
- 따라서 두 요청이 모두 끝나려면 8초가 걸린다.
2. WebClient
- Spring 5에서 도입된 비동기, non-blocking, reactive 웹 클라이언트이다.
- Project Reactor를 기반으로 하며, 비동기 처리와 백프레셔(Backpressure)를 지원한다.
- RestTemplate보다 더 효율적인 리소스 사용이 가능하며, 대량의 요청을 처리하는데 적합하다.
- RestTemplate이 deprecated된 이후, WebClient가 RESTful 서비스를 호출하는 주요 도구가 되었다.
WebClient webClient = WebClient.create();
Mono<String> result = webClient.get()
.uri(url)
.retrieve()
.bodyToMono(String.class);
- Non-Blocking I/O 기반의 Asynchronous API
- WebClientAutoConfiguration
- 프로젝트에 spring-webflux 모듈이 있다면 WebClient.Builder를 빈으로 등록
방법2. WebClient.Builder를 주입받아 WebClient 생성
- get().uri().retrieve().bodyToMono(String.class)로 GET요청 보내기
- Stream API를 사용하기 때문에 subscribe()로 결과를 반환해야 함
- non-blocking i/o : 호출된 함수가 바로 결과를 반환하여, 호출한 함수에게 제어권을 바로 넘겨준다.
- async : 호출된 함수의 작업 완료 여부를 신경쓰지 않기 때문에, 작업 완료 시 호출된 함수는 전달받은 콜백을 실행하기만 한다.
cf) subscribe()는 Javascript의 .then()을 생각하면 될 듯!
Promise 객체가 fulfilled되도 then을 쓰지 않으면 resolve()의 인자값을 꺼낼 수 없는 것처럼
내가 보냈던 요청에 대한 응답 이벤트를 받을 때, 어떤 행동을 수행할 것인지 이벤트 핸들러를 정의해주는 일이다.
@Component
public class RestRunner implements ApplicationRunner {
@Autowired
WebClient.Builder webClientBuilder;
@Override
public void run(ApplicationArguments args) throws Exception {
WebClient webClient = webClientBuilder.build();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Mono<String> helloResult = webClient.get().uri("<http://localhost:8080/hello>")
.retrieve()
.bodyToMono(String.class);
helloResult.subscribe(result -> {
System.out.println(result);
if (stopWatch.isRunning()){
stopWatch.stop();
}
System.out.println(stopWatch.prettyPrint());
stopWatch.start();
});
Mono<String> worldResult = webClient.get().uri("<http://localhost:8080/sample>")
.retrieve()
.bodyToMono(String.class);
worldResult.subscribe(result -> {
System.out.println(result);
if (stopWatch.isRunning()){
stopWatch.stop();
}
System.out.println(stopWatch.prettyPrint());
stopWatch.start();
});
}
}
- 3초 째에 "hello"를 출력하고, 5초 째에 "sample"을 출력한다.
- async-nonblocking : /hello GET요청과 /sample GET요청이 병렬적으로 수행된다.
- 따라서 두 요청이 모두 끝나려면 5초가 걸린다.
스프링 REST Client 커스터마이징
WebClient 커스터마이징
- webClientBuilder.build()로 빌드하기 전에 필요한 설정 가능
- baseUrl("http://localhost:8080")
- defaultCookie( )
- defaultHeader( )
- 글로벌 WebClient 객체 사용하기
- WebClientCustomizer 빈 재정의
- ApplicationContext에서 전역적으로 적용한다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.run(args);
}
@Bean
public WebClientCustomizer webClientCustomizer(){
return new WebClientCustomizer() {
@Override
public void customize(WebClient.Builder webClientBuilder) {
webClientBuilder.baseUrl("<http://localhost:8080>");
}
};
}
}
RestTemplate 커스터마이징
- RestTemplateBuilder 빈 재정의
- org.apache.httpcomponents:httpclient 의존성 추가 필요
- 마찬가지로 ApplicationContext에서 전역적으로 정의
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Application.class);
app.run(args);
}
@Bean
public RestTemplateCustomizer restTemplateCustomizer() {
return new RestTemplateCustomizer() {
@Override
public void customize(RestTemplate restTemplate) {
restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory());
}
};
}
}
728x90
반응형
LIST
'일상 > 스터디' 카테고리의 다른 글
6일차 과제 - 트랜잭션이 무엇인지 설명해 주세요. (0) | 2023.05.15 |
---|---|
5일차 과제 - @SpringBootTest와 @WebMvcTest의 차이점 (0) | 2023.05.13 |
4일차 과제 - 스프링 컨테이너 (0) | 2023.05.12 |
3일차 과제 제네릭, 컬렉션 클래스 (0) | 2023.05.12 |
4일차 과제 List, Set, Map, HashMap의 차이 (0) | 2023.05.11 |