Spring Boot 공부 일기 <14> - WebClient

이동휘·2024년 8월 24일

Spring Boot

목록 보기
14/21

1. IDE

Intellij

2. 오늘 공부 내용

WebClient

  • WebClient - 비동기 방식으로 작업을 처리할 수 있어, 대규모 데이터 처리나 높은 성능이 필요한 애플리케이션에 적합
    • 서버로부터의 응답을 논블로킹 방식으로 처리할 수 있음

WebClient의 주요 특징

  • 비동기 및 논블로킹: WebClient는 비동기 요청을 지원하며, 논블로킹 방식으로 동작합니다. 요청을 보낸 후 응답을 기다리는 동안 다른 작업을 수행할 수 있어, 리소스 사용 효율이 높습니다.
  • 리액티브 프로그래밍 지원: WebClient는 Reactor 라이브러리 기반으로, MonoFlux를 사용해 리액티브 스트림을 처리할 수 있습니다. 이는 대규모 데이터 처리에 적합한 방법입니다.
  • 유연한 API: WebClient는 요청과 응답의 각 부분을 세밀하게 제어할 수 있는 유연한 API를 제공합니다. HTTP 요청 헤더, 쿠키, URI 템플릿 등을 쉽게 설정할 수 있습니다.
  • 상태 저장 클라이언트: WebClient는 쿠키와 세션을 사용하여 상태를 저장할 수 있습니다. 이는 RESTful API 호출 시 동일한 상태를 유지해야 할 때 유용합니다.
  • 플러그블(Plugable): WebClient는 사용자 정의 코덱, 변환기, 로깅, 필터 등을 쉽게 추가할 수 있는 플러그블 구조를 가지고 있습니다.

WebClient 사용 방법

  1. 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();
  1. 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(): 비동기적으로 결과를 처리합니다
  1. 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()를 사용해 비동기적으로 데이터를 감싸서 보낼 수 있습니다.
  1. 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();
  1. HTTP DELETE 요청
Mono<Void> responseMono = webClient.delete()
        .uri("/users/{id}", 1)
        .retrieve()
        .bodyToMono(Void.class);

responseMono.subscribe();
  1. 요청 및 응답 헤더 설정
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()));
  1. 에러 처리
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의 고급 기능

  1. 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);
  1. 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();
  1. 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 요청의 모든 측면을 제어할 수 있는 다양한 기능을 제공하며, 대규모 애플리케이션 개발에 적합한 도구

0개의 댓글