1. IDE
Intellij
2. 오늘 공부 내용
WebClient
- WebClient - 비동기 방식으로 작업을 처리할 수 있어, 대규모 데이터 처리나 높은 성능이 필요한 애플리케이션에 적합
- 서버로부터의 응답을 논블로킹 방식으로 처리할 수 있음
WebClient의 주요 특징
- 비동기 및 논블로킹: WebClient는 비동기 요청을 지원하며, 논블로킹 방식으로 동작합니다. 요청을 보낸 후 응답을 기다리는 동안 다른 작업을 수행할 수 있어, 리소스 사용 효율이 높습니다.
- 리액티브 프로그래밍 지원: WebClient는 Reactor 라이브러리 기반으로,
Mono와 Flux를 사용해 리액티브 스트림을 처리할 수 있습니다. 이는 대규모 데이터 처리에 적합한 방법입니다.
- 유연한 API: WebClient는 요청과 응답의 각 부분을 세밀하게 제어할 수 있는 유연한 API를 제공합니다. HTTP 요청 헤더, 쿠키, URI 템플릿 등을 쉽게 설정할 수 있습니다.
- 상태 저장 클라이언트: WebClient는 쿠키와 세션을 사용하여 상태를 저장할 수 있습니다. 이는 RESTful API 호출 시 동일한 상태를 유지해야 할 때 유용합니다.
- 플러그블(Plugable): WebClient는 사용자 정의 코덱, 변환기, 로깅, 필터 등을 쉽게 추가할 수 있는 플러그블 구조를 가지고 있습니다.
WebClient 사용 방법
- WebClient 인스턴스 생성
- 기본 생성: 가장 기본적인 WebClient 인스턴스 생성 방법입니다.
WebClient webClient = WebClient.create();
- 기본 URI 설정: 기본 URI를 설정하여 인스턴스를 생성합니다.
WebClient webClient = WebClient.create("https://api.example.com");
- 빌더를 사용한 설정: WebClient.Builder를 사용해 더 정교하게 설정할 수 있습니다.
WebClient webClient = WebClient.builder()
.baseUrl("https://api.example.com")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
- HTTP GET 요청
Mono<User> userMono = webClient.get()
.uri("/users/{id}", 1)
.retrieve()
.bodyToMono(User.class);
userMono.subscribe(user -> System.out.println(user.getName()));
retrieve(): 응답을 처리할 준비를 하며, 요청을 전송합니다.
bodyToMono(): 응답 본문을 Mono로 변환합니다. 이는 단일 객체를 반환할 때 사용됩니다.
subscribe(): 비동기적으로 결과를 처리합니다
- HTTP POST 요청
Mono<User> createdUserMono = webClient.post()
.uri("/users")
.body(Mono.just(new User("John", "Doe")), User.class)
.retrieve()
.bodyToMono(User.class);
createdUserMono.subscribe(user -> System.out.println(user.getId()));
body(): 요청 본문에 데이터를 포함시킵니다. Mono.just()를 사용해 비동기적으로 데이터를 감싸서 보낼 수 있습니다.
- HTTP PUT 요청
Mono<Void> responseMono = webClient.put()
.uri("/users/{id}", 1)
.body(Mono.just(new User("John", "Doe")), User.class)
.retrieve()
.bodyToMono(Void.class);
responseMono.subscribe();
- HTTP DELETE 요청
Mono<Void> responseMono = webClient.delete()
.uri("/users/{id}", 1)
.retrieve()
.bodyToMono(Void.class);
responseMono.subscribe();
- 요청 및 응답 헤더 설정
Mono<User> userMono = webClient.get()
.uri("/users/{id}", 1)
.header(HttpHeaders.AUTHORIZATION, "Bearer your_token_here")
.retrieve()
.bodyToMono(User.class);
userMono.subscribe(user -> System.out.println(user.getName()));
- 에러 처리
Mono<User> userMono = webClient.get()
.uri("/users/{id}", 1)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse -> {
return Mono.error(new RuntimeException("Client Error!"));
})
.onStatus(HttpStatus::is5xxServerError, clientResponse -> {
return Mono.error(new RuntimeException("Server Error!"));
})
.bodyToMono(User.class);
userMono.subscribe(user -> System.out.println(user.getName()),
error -> System.out.println("Error: " + error.getMessage()));
WebClient의 고급 기능
- Body Inserters - 요청 본문을 다양한 형식으로 추가할 수 있습니다.
WebClient webClient = WebClient.create();
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
formData.add("name", "John");
formData.add("age", "30");
Mono<Void> response = webClient.post()
.uri("/users")
.body(BodyInserters.fromFormData(formData))
.retrieve()
.bodyToMono(Void.class);
- WebClient Filters - 요청과 응답의 처리 과정에서 필터를 적용할 수 있습니다.
WebClient webClient = WebClient.builder()
.filter((request, next) -> {
System.out.println("Request: " + request.method() + " " + request.url());
return next.exchange(request)
.doOnNext(response -> {
System.out.println("Response: " + response.statusCode());
});
})
.build();
- WebClient와 리액티브 연산 - 리액티브 스트림을 지원하며, Flux와 Mono를 조합해 비동기 스트림을 처리할 수 있습니다.
Flux<User> userFlux = webClient.get()
.uri("/users")
.retrieve()
.bodyToFlux(User.class);
userFlux.filter(user -> user.getAge() > 18)
.flatMap(user -> webClient.get()
.uri("/details/{id}", user.getId())
.retrieve()
.bodyToMono(UserDetails.class))
.subscribe(details -> System.out.println(details.getInfo()));
결론
- WebClient는 Spring 5와 함께 도입된 강력한 HTTP 클라이언트로, 비동기 및 논블로킹 방식으로 HTTP 요청을 처리할 수 있습니다
- RestTemplate에 비해 유연성과 확장성이 뛰어나며, 특히 리액티브 프로그래밍을 지원하는 애플리케이션에서 매우 유용
- WebClient는 HTTP 요청의 모든 측면을 제어할 수 있는 다양한 기능을 제공하며, 대규모 애플리케이션 개발에 적합한 도구