본문 바로가기

Spring WebFlux와 비동기 처리 이해 본문

Backend

Spring WebFlux와 비동기 처리 이해

00rigin 2025. 4. 30. 11:02

Spring WebFlux비동기논블로킹 웹 애플리케이션을 개발하는 데 유용한 프레임워크이다. WebFlux는 Reactive Programming을 기반으로 하며, MonoFlux를 사용하여 비동기적으로 데이터를 처리할 수 있다. 이번 글에서는 Spring WebFluxSpring MVC의 차이점, MonoFlux의 활용 방법에 대해 정리해본다.

1. Spring MVC와 Spring WebFlux

Spring MVC란?

Spring MVCModel-View-Controller 패턴을 따르는 전통적인 동기식 웹 애플리케이션 프레임워크이다. 클라이언트의 요청이 들어오면, 요청을 처리하는 컨트롤러가 동기적으로 응답을 반환한다. 요청을 처리하는 동안 스레드가 차단되며, 한 번에 하나의 요청만 처리할 수 있다. 이 방식은 짧은 응답 시간을 요구하는 시스템에서는 적합하지만, 동시성이 높은 트래픽을 처리하기에는 한계가 있다.

Spring MVC의 특징:

  • 동기식 처리: 각 요청은 하나의 스레드에서 처리되고, 해당 요청을 끝내야 다른 요청을 처리할 수 있다.
  • 블로킹 I/O: 요청과 응답 처리 과정에서 스레드가 블로킹되어 다른 요청을 처리할 수 없다.
  • 서블릿 기반: 기본적으로 Tomcat과 같은 서블릿 컨테이너에서 실행된다.

Spring WebFlux란?

Spring WebFluxSpring 5에서 도입된 비동기논블로킹 처리 기반의 웹 애플리케이션 프레임워크이다. WebFlux는 Reactive Programming을 기반으로 하며, MonoFlux를 사용해 반응형 스트림을 처리한다. 이는 고동시성 처리대규모 트래픽 처리에 적합하다.

Spring WebFlux의 특징:

  • 비동기 및 논블로킹 처리: 요청을 비동기적으로 처리하여, 하나의 스레드가 여러 요청을 처리할 수 있다.
  • Reactive Streams: MonoFlux를 사용해 데이터를 비동기적으로 처리한다.
  • 서블릿 기반이 아님: Netty, Undertow와 같은 논블로킹 서버에서 주로 실행된다.

Spring MVC vs Spring WebFlux

특징 Spring MVC Spring WebFlux
동작 방식 동기식 요청 처리, 각 요청마다 스레드 차단 비동기식 요청 처리, 요청 처리 중 다른 작업 병행 가능
서버 Tomcat, 서블릿 컨테이너 사용 Netty, Undetow 등의 논블로킹 서버 사용
적합한 환경 전통적인 웹 애플리케이션, 트래픽이 적은 시스템 동시 요청이 많은 시스템, I/O 바운드 작업이 많은 시스템
성능 스레드 수에 비례하는 성능 제한 높은 동시성 처리, 적은 리소스로 높은 성능 발휘

2. Mono와 Flux

WebFlux에서 중요한 역할을 하는 두 가지 타입은 MonoFlux이다. 두 타입은 Reactive Programming의 핵심으로, 각각 단일 값다수의 값을 처리하는 데 사용된다.

Mono

  • Mono0개 또는 1개의 아이템을 처리하는 반응형 데이터 스트림이다.
  • Mono단일 결과를 처리하거나 없을 수도 있는 값을 처리하는 데 유용하다.

Mono 예시:

import reactor.core.publisher.Mono

fun getUserById(userId: Long): Mono<User> {
    return Mono.justOrEmpty(userRepository.findById(userId))
}

위 예시에서 Mono.justOrEmpty()는 주어진 값이 있을 수도, 없을 수도 있음을 나타낸다.

Flux

  • Flux0개 이상의 아이템을 처리하는 반응형 데이터 스트림이다.
  • Flux는 여러 값을 반환할 수 있으며, 순차적 또는 병렬적으로 처리할 수 있다.

Flux 예시:

import reactor.core.publisher.Flux

fun getAllUsers(): Flux<User> {
    return Flux.fromIterable(userRepository.findAll())
}

위 예시에서 Flux.fromIterable()은 여러 사용자의 데이터를 비동기적으로 처리하고 반환한다.

3. Mono와 Flux의 차이점

특징 Mono Flux
아이템 개수 0개 또는 1개 0개 이상의 아이템
비동기 처리 1개의 값을 비동기적으로 처리 여러 값을 비동기적으로 처리
예시 데이터베이스에서 단일 사용자 조회 여러 사용자 데이터를 스트리밍하거나 처리

Mono와 Flux 활용

  • Mono단일 값을 반환할 때 유용하다. 예를 들어, 데이터베이스에서 한 명의 사용자 정보를 조회할 때 사용된다.
  • Flux여러 값을 반환할 때 유용하다. 예를 들어, 실시간 데이터 스트리밍이나 대규모 데이터베이스 결과를 처리할 때 사용된다.

4. Spring WebFlux Controller

WebFlux는 @RestController를 사용하여 웹 요청을 처리한다. MonoFlux를 반환하여 비동기적 응답을 처리할 수 있다.

WebFlux Controller 예시:

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
import reactor.core.publisher.Mono

@RestController
class UserController(private val userService: UserService) {

    @GetMapping("/user/{id}")
    fun getUserById(@PathVariable id: Long): Mono<User> {
        return userService.getUserById(id)
    }

    @GetMapping("/users")
    fun getAllUsers(): Flux<User> {
        return userService.getAllUsers()
    }
}
  • getUserById: Mono를 반환하여 단일 사용자 데이터를 비동기적으로 처리.
  • getAllUsers: Flux를 반환하여 여러 사용자의 데이터를 비동기적으로 처리.

비동기 처리의 장점

  • 효율적인 리소스 관리: 요청을 처리하는 동안 다른 작업을 병행할 수 있어, 서버의 리소스를 효율적으로 사용할 수 있다.
  • 높은 동시성 처리: 많은 수의 동시 요청을 처리하는 데 유리하다. 특히 I/O 바운드 작업이 많은 경우 성능을 크게 개선할 수 있다.

5. 비동기 흐름 처리 방법

WebFlux에서는 비동기 흐름을 처리하기 위한 여러 연산자를 제공한다. map, flatMap, filter 등을 사용하여 데이터를 처리하고, 필요한 경우 오류 처리도 가능하다.

비동기 데이터 처리 예시:

fun getActiveUsers(): Flux<User> {
    return userRepository.findAll()
        .filter { it.status == "ACTIVE" }
        .map { it.copy(name = it.name.uppercase()) }
}

이 예시는 filtermap을 사용하여 활성 사용자만 필터링하고, 이름을 대문자로 변환하는 비동기 흐름을 처리한다.

오류 처리 예시:

Flux.just("a", "b", "c")
    .map {
        if (it == "b") throw RuntimeException("Error!")
        it
    }
    .onErrorResume { Flux.just("fallback") }  // 오류 발생 시 대체 값 반환
    .subscribe { println(it) }  // 출력: a, fallback, c

이 예시는 onErrorResume을 사용하여 오류가 발생한 경우 대체 값을 반환하도록 처리한다.

6. 결론

Spring WebFlux비동기논블로킹 처리에 최적화된 웹 프레임워크로, MonoFlux를 활용한 비동기 데이터 흐름 처리에 매우 유용하다. 이를 통해 고성능의 웹 애플리케이션을 구축할 수 있으며, 다수의 동시 요청을 효율적으로 처리할 수 있다.

  • Mono단일 값을 처리할 때,
  • Flux여러 값을 처리할 때 사용된다.
  • 비동기 처리를 통해 리소스를 효율적으로 관리하고, 동시성을 높일 수 있다.

Spring WebFluxSpring MVC의 차이점을 이해하고, 각각의 장단점을 잘 활용하면 대규모 시스템에서 성능을 최적화하는 데 큰 도움이 될 것이다.

7. 추가 정보: Tomcat에서 비동기 처리 사용하기

Tomcat은 기본적으로 동기식 서버로 작동하지만, 서블릿 3.0부터 비동기 처리를 지원한다. Tomcat에서 비동기 처리를 사용하면 비동기 요청을 처리할 수 있게 되며, 특정 요청을 처리하는 동안 다른 요청을 처리할 수 있다.

Tomcat에서 비동기 처리 방법

Tomcat에서 비동기 처리를 사용하려면, Servlet 3.0 이상의 버전에서 제공하는 async 기능을 활성화해야 한다. 아래는 Tomcat에서 비동기 처리를 설정하는 방법이다.

@WebServlet(urlPatterns = "/async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 비동기 처리 시작
        AsyncContext asyncContext = request.startAsync();
        asyncContext.start(() -> {
            // 비동기 작업 수행
            try {
                Thread.sleep(2000);  // 예시: 비동기 작업
                asyncContext.getResponse().getWriter().write("Async Processing Complete");
            } catch (InterruptedException | IOException e) {
                e.printStackTrace();
            } finally {
                asyncContext.complete();
            }
        });
    }
}

이렇게 설정하면 요청을 비동기적으로 처리할 수 있지만, Tomcat은 여전히 내부적으로 동기적인 방식으로 처리되므로 비동기 성능에서 NettyUndertow와 같은 논블로킹 서버에는 미치지 않는다.

한계점

  • 스레드 관리: Tomcat에서 비동기 처리를 하더라도 스레드 풀의 크기나 디스크 I/O 처리와 같은 제한이 있기 때문에, 비동기 처리의 효과가 제한적일 수 있다.
  • 논블로킹 서버의 이점 미비: Tomcat은 서블릿 기반이기 때문에 Netty와 같은 논블로킹 서버의 성능을 충분히 활용하지 못한다.
  • 내부 구현 한계: Tomcat의 내부 구현서블릿 스펙을 따르기 때문에 비동기 처리를 하더라도 결국 동기적으로 동작하는 부분이 많다. 요청을 비동기적으로 처리할 수 있는 구조가 있지만, Tomcat은 여전히 동기적인 스레드 모델을 기반으로 동작하므로, 비동기 성능을 최대로 활용할 수 없다. NettyUndertow와 같은 서버는 비동기 및 논블로킹 아키텍처로 설계되어 있어 이러한 제약 없이 비동기 성능을 극대화할 수 있다.

따라서 Tomcat에서 비동기 처리를 사용하더라도, 고성능 비동기 시스템을 구축하고자 한다면 Netty와 같은 논블로킹 서버를 사용하는 것이 더 적합하다.

'Backend' 카테고리의 다른 글

[MySql] 인덱싱 개념 정리  (0) 2025.04.29
Kafka.00 카프카 개요  (0) 2025.03.06
Lambda@Edge를 사용한 이미지 리사이징 적용기  (0) 2025.02.25
Intellij 에서 Springboot 시작하기  (0) 2023.01.15
Comments