Spring 기반의 웹 애플리케이션을 개발할 때 Spring Web (Spring MVC)과 Spring WebFlux 중 어떤 것을 선택해야 할지 고민한 적이 있나요? 두 기술은 웹 애플리케이션을 만들 수 있는 강력한 도구이지만, 동작 방식이 다릅니다. 이 글에서는 둘의 동작 방식의 차이를 다뤄보고자 합니다.
| 특징 | Spring Web (MVC) | Spring WebFlux |
|---|---|---|
| 기본 실행 방식 | 동기(Blocking) | 비동기(Non-Blocking) |
| 기반 기술 | Servlet API (Thread-per-request) | Reactive Streams (Event-driven) |
| 기본 컨테이너 | Tomcat, Jetty 등 | Netty, Undertow 등 |
| 데이터 처리 | 동기 방식 (Blocking I/O) | 리액티브 스트림 기반 (Non-Blocking I/O) |
Spring Web은 전통적인 MVC 패턴을 사용하며 요청이 들어오면 스레드가 하나 할당되어 작업을 수행합니다. 반면, WebFlux는 논블로킹 방식으로 이벤트 기반 처리 모델을 따릅니다.
동기 방식(Spring Web)에서는 요청이 들어오면 Controller - Service - Repository - DB 과정을 하나의 스레드가 담당합니다.
이 과정에서 데이터베이스나 외부 API를 호출하는 동안 해당 스레드는 결과가 반환될 때까지 대기(Blocking) 상태에 놓이게 됩니다. 이로 인해 동시 요청이 많아질 경우 서버의 스레드 풀(Thread Pool)이 빠르게 소진되면서 성능이 저하될 수 있습니다.
비동기 방식(Spring WebFlux)에서는 요청이 들어오면 이벤트 기반(Event-driven) 모델이 작동합니다. 즉,
Spring WebFlux에서 Mono와 Flux는 비동기 데이터를 다루기 위한 핵심 클래스입니다. 이들은 리액티브 스트림(Reactive Streams)을 기반으로 하며, 기존의 Future 또는 CompletableFuture보다 유연하게 데이터를 다룰 수 있습니다.
Spring WebFlux에서는 비동기 데이터 처리를 위해 Mono와 Flux를 사용합니다.
Mono: 0개 또는 1개의 값을 반환하는 비동기 객체입니다. 단일 데이터를 처리할 때 사용됩니다.
Mono<String> monoExample = Mono.just("Hello, Mono!");
위 코드에서 Mono.just("Hello, Mono!")는 "Hello, Mono!" 값을 감싸 비동기적으로 반환합니다.
Flux: 0개 이상의 여러 값을 반환하는 비동기 객체입니다. 스트리밍 데이터나 컬렉션을 처리할 때 사용됩니다.
Flux<String> fluxExample = Flux.just("Hello", "Flux", "World!");
위 코드에서 Flux.just("Hello", "Flux", "World!")는 3개의 값을 순차적으로 반환할 수 있습니다.
Mono와 Flux가 0개 혹은 그 이상의 데이터를 반환할 수 있는 이유는, 비동기 환경에서 데이터의 가용성을 보장하기 위해 설계되었기 때문입니다.
이러한 구조는 WebFlux가 데이터의 흐름을 제어하고, 백프레셔(Backpressure)를 활용하여 소비자(Consumer)의 처리 속도에 맞춰 데이터를 제공할 수 있도록 도와줍니다.
Microservices Architecture(MSA)에서는 API Gateway가 많은 트래픽을 처리해야 합니다. 이때 비동기 방식이 효과적인 이유는 다음과 같습니다.