1️⃣ WebClient
- Spring 5부터 지원하는, Spring WebFlux에서 제공하는 비동기식 HTTP 클라이언트
- 주로 서버 측에서 다른 API나 웹 서비스와 통신하기 위해 사용됩니다.
- 브라우저에서 동작하는 클라이언트 애플리케이션을 직접 개발하기 위한 도구는 아닙니다.
- 서버 측에서 HTTP 요청을 보낼 수 있게 해주는 역할을 합니다.
- Non-Blocking, Blocking HTTP 요청을 모두 지원
- Spring MVC의 RestTemplate (Blocking)을 대체할 수 있습니다.
WebClient가 필요한 이유
WebClient는 서버 사이드 애플리케이션에서 다른 서비스와 통신할 때 유용합니다.
- 마이크로서비스 간 통신:
- 마이크로서비스 아키텍처에서 서비스 간 통신이 필요할 때, WebClient를 사용해 다른 서비스의 API에 비동기 요청을 보낼 수 있습니다.
- 외부 API 호출:
- 외부의 RESTful API나 웹 서비스를 호출해야 할 때, WebClient를 통해 비동기식으로 데이터를 요청하고 처리할 수 있습니다.
- 예를 들어, 날씨 API, 금융 정보 API, 소셜 미디어 API 등을 호출할 때 사용할 수 있습니다.
참고 : 비동기와 논블로킹
비동기 : 작업을 처리하는 방식을 설명. 작업의 완료 시점이 현재 흐름에 의존하지 않는다.
논블로킹 : 자원의 동작 방식을 설명. 현재 자원이 대기 상태에 들어가지 않고(블로킹x), 다른 작업을 계속 수행할 수 있는 상태를 유지한다.
2️⃣ 코드 예시 : 도서 정보 요청
| 참고 : 스프링으로 시작하는 리액티브 프로그래밍(황정식)
POST 요청
@Slf4j
@Configuration
public class WebClientExample01 {
@Bean
public ApplicationRunner examplesWebClient() {
return (ApplicationArguments arguments) -> {
exampleWebClient01();
};
}
private void exampleWebClient01() {
BookDto.Post requestBody = new BookDto.Post("Java 중급",
"Intermediate Java",
"Java 중급 프로그래밍 마스터",
"Kevin1", "222-22-2222-222-2",
"2022-03-22");
WebClient webClient = WebClient.create();
Mono<ResponseEntity<Void>> response =
webClient
.post()
.uri("http://localhost:8080/v10/books")
.bodyValue(requestBody)
.retrieve()
.toEntity(Void.class);
response.subscribe(res -> {
log.info("response status: {}", res.getStatusCode());
log.info("Header Location: {}", res.getHeaders().get("Location"));
});
}
}
PATCH 요청
@Slf4j
@Configuration
public class WebClientExample01 {
@Bean
public ApplicationRunner examplesWebClient() {
return (ApplicationArguments arguments) -> {
exampleWebClient02();
};
}
private void exampleWebClient02() {
BookDto.Patch requestBody =
new BookDto.Patch.PatchBuilder().titleKorean("Java 고급")
.titleEnglish("Advanced Java")
.description("Java 고급 프로그래밍 마스터")
.author("Tom")
.build();
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<BookDto.Response> response =
webClient
.patch()
.uri("http://localhost:8080/v10/books/{book-id}", 20)
.bodyValue(requestBody)
.retrieve()
.bodyToMono(BookDto.Response.class);
response.subscribe(book -> {
log.info("bookId: {}", book.getBookId());
log.info("titleKorean: {}", book.getTitleKorean());
log.info("titleEnglish: {}", book.getTitleEnglish());
log.info("description: {}", book.getDescription());
log.info("author: {}", book.getAuthor());
});
}
}
GET 요청
@Slf4j
@Configuration
public class WebClientExample01 {
@Bean
public ApplicationRunner examplesWebClient() {
return (ApplicationArguments arguments) -> {
exampleWebClient03();
exampleWebClient04();
};
}
private void exampleWebClient03() {
Mono<BookDto.Response> response =
WebClient
.create("http://localhost:8080")
.get()
.uri(uriBuilder -> uriBuilder
.path("/v10/books/{book-id}")
.build(21))
.retrieve()
.bodyToMono(BookDto.Response.class);
response.subscribe(book -> {
log.info("bookId: {}", book.getBookId());
log.info("titleKorean: {}", book.getTitleKorean());
log.info("titleEnglish: {}", book.getTitleEnglish());
log.info("description: {}", book.getDescription());
log.info("author: {}", book.getAuthor());
});
}
private void exampleWebClient04() {
Flux<BookDto.Response> response =
WebClient
.create("http://localhost:8080")
.get()
.uri(uriBuilder -> uriBuilder
.path("/v10/books")
.queryParam("page", "1")
.queryParam("size", "10")
.build())
.retrieve()
.bodyToFlux(BookDto.Response.class);
response
.map(book -> book.getTitleKorean())
.subscribe(bookName -> log.info("book name: {}", bookName));
}
}
'Reactive Programming' 카테고리의 다른 글
240815 Reactive Streaming 데이터 처리 (0) | 2024.08.15 |
---|---|
240809금 Spring Data R2DBC (0) | 2024.08.09 |
240804 Spring MVC vs Spring WebFlux (0) | 2024.08.04 |
240804 Operators :: Sequence 내부 동작 확인 (0) | 2024.08.04 |
240804 Operators :: Sequence 변환 (0) | 2024.08.04 |