안녕하세요.
이번에는 Spring WebFlux에 대해서 공부해보겠습니다.
Spring WebFlux는 Spring Framework 5에서 도입된 비동기 논블로킹(Asynchronous Non-Blocking) 방식의 웹 프레임워크입니다.
기존 Spring MVC가 Servlet 기반의 동기 블로킹 모델을 사용했다면, WebFlux는 Reactor 기반의 논블로킹 스트림 처리를 지원하여 높은 확장성과 성능을 제공합니다.
이번 글에서는 Spring WebFlux의 개념, 기본적인 사용법, 주요 특징을 코드와 함께 공부해보겠습니다.
| 특성 | Spring MVC | Spring WebFlux |
|---|---|---|
| 동작 방식 | 동기 블로킹 | 비동기 논블로킹 |
| 요청 처리 | 하나의 요청당 하나의 쓰레드 | 하나의 쓰레드가 여러 요청을 처리 |
| Reactor 지원 | ❌ | ✅ |
| WebClient 사용 | ❌ (RestTemplate 사용) | ✅ (WebClient 사용) |
| 사용 사례 | 일반적인 웹 애플리케이션 | 대량의 요청 처리, 고성능 API 서버 |
WebFlux는 대표적으로 Reactor 라이브러리의 Mono와 Flux를 사용하여 데이터를 비동기적으로 다룹니다.
dependencies {
// https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux
implementation("org.springframework.boot:spring-boot-starter-webflux:3.4.2")
// https://mvnrepository.com/artifact/io.projectreactor/reactor-core
implementation("io.projectreactor:reactor-core:3.7.3")
// https://mvnrepository.com/artifact/io.projectreactor.netty/reactor-netty
implementation("io.projectreactor.netty:reactor-netty:1.2.3")
}
Spring WebFlux에서는 @RestController를 그대로 사용할 수 있으며, 반환 타입으로 Mono 또는 Flux를 활용합니다.
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.time.Duration;
@RestController
@RequestMapping("/webflux")
public class WebFluxController {
@GetMapping("/mono")
public Mono<String> getMono() {
return Mono.just("Hello, WebFlux!").delayElement(Duration.ofSeconds(1));
}
@GetMapping("/flux")
public Flux<Integer> getFlux() {
return Flux.range(1, 5).delayElements(Duration.ofSeconds(1));
}
}
GET /webflux/mono → 1초 후 "Hello, WebFlux!" 반환GET /webflux/flux → 1초 간격으로 1~5까지 숫자 반환WebClient는 WebFlux에서 제공하는 비동기 HTTP 클라이언트로, 기존 RestTemplate을 대체하는 방식입니다. WebClient는 논블로킹 방식의 HTTP 요청을 수행하며, Mono와 Flux를 사용하여 데이터를 처리합니다.
WebClient란?
WebClient는 Spring WebFlux에서 제공하는 비동기 논블로킹(Asynchronous Non-Blocking) HTTP 클라이언트입니다.
기존 Spring MVC에서 RestTemplate을 사용하여 HTTP 요청을 수행했던 것과 달리, WebClient는 비동기 방식으로 HTTP 요청을 처리할 수 있습니다. 즉, WebClient를 사용하면 서버 간의 네트워크 통신을 효율적으로 처리하면서도, 높은 성능과 확장성을 갖춘 API를 만들 수 있습니다.
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class WebClientExample {
public static void main(String[] args) {
WebClient webClient = WebClient.create("http://localhost:8080");
Mono<String> response = webClient.get()
.uri("/webflux/mono")
.retrieve()
.bodyToMono(String.class);
response.subscribe(System.out::println);
}
}
위 코드를 실행하면 비동기적으로 HTTP 요청을 수행하고 응답을 Mono로 받아 처리합니다.
WebClient는 GET, POST, PUT, DELETE 요청을 지원하며, retrieve() 또는 exchangeToMono()를 통해 응답을 처리할 수 있습니다.
Mono<String> response = WebClient.create()
.get()
.uri("http://localhost:8080/webflux/mono")
.retrieve()
.bodyToMono(String.class);
Mono<String> response = WebClient.create()
.post()
.uri("http://localhost:8080/webflux/data")
.bodyValue("Sample Data")
.retrieve()
.bodyToMono(String.class);
WebClient.create()
.get()
.uri("http://localhost:8080/webflux/mono")
.retrieve()
.onStatus(HttpStatus::is4xxClientError, clientResponse ->
Mono.error(new RuntimeException("Client Error!")))
.onStatus(HttpStatus::is5xxServerError, clientResponse ->
Mono.error(new RuntimeException("Server Error!")))
.bodyToMono(String.class);
WebFlux에서 제공하는 Mono와 Flux는 비동기 데이터 스트림을 처리하는데 강력한 기능을 제공합니다.
Mono와 Flux 차이| 타입 | 설명 |
|---|---|
Mono<T> | 최대 1개의 데이터를 처리 |
Flux<T> | 0개 이상의 데이터를 스트림 형태로 처리 |
Flux<Integer> fluxStream = Flux.range(1, 5)
.map(num -> num * 2)
.filter(num -> num > 5);
fluxStream.subscribe(System.out::println);
이 코드는 1~5의 숫자에 2를 곱하고, 5보다 큰 숫자만 출력합니다.
출력 결과:
6
8
10
Spring WebFlux는 높은 확장성을 제공하지만, 다음과 같은 고려사항이 필요합니다.
이번 글에서는 Spring WebFlux의 개념과 사용법을 공부해봤습니다.
Mono와 Flux를 이용해 데이터 스트림을 다룬다.WebClient를 활용해 비동기 HTTP 요청을 처리할 수 있다.듣기만 해봤지 실제로 이론을 공부하는건 처음이였는데요.
중간 중간 처음보는 방식과 내용이 있었습니다. 우선은 전체적인 개념을 위주로 정리해보았습니다.
제가 알아보며 궁금했던
비동기 논블로킹 방식을 지원하는 Mono 또는 Flux,
비동기 논블로킹 HTTP 클라이언트인 WebClient에 대해서 심층적으로 분석해보고자 합니다.
또한 추가적으로 알게된 내용이 있다면 잊어버리지 않도록 같이 작성할 예정입니다.
읽어주셔서 감사합니다.