Spring Webflux
출처 : https://summsu84.tistory.com/29
개요
Spring Framework, Spring MVC 는 Servlet API 및 Servlet Container 에서 동작 하도록 만들어졌으나, Reactive 웹 프레임워크인 Spring WebFlux 는 비동기/논블럭킹 방식으로 웹 애플리케이션 개발 할 수 있게 해주는 모듈입니다. Spring WebFlux 는 Spring 5.0 이후에 추가 되었으며, Reactive 프로그래밍 패러다임에 기반하며, Netty, Undertow, 그리고 Tocmat 서블릿 컨테이너위에서 동작 합니다. 기존 Spring MVC 와 다르게 Spring WebFlux 적은 리소스로 더 많은 요청을 제공 합니다.
동작 원리
Spring MVC
일반적으로 사용되는 Spring MVC 는 쓰레드 풀 기반으로 동작 한다. 위 그림과 같이 요청이 들어오게 되면, 쓰레드 풀에 있는 요청 정보를 사용하고, 응답이 되면 해당 요청 정보를 반환하게 된다. 즉, 한 개의 요청에 대해서 한 개의 쓰레드를 사용하게 된다. 이는 DBCP 를 사용하는 이유와 같이, 쓰레드를 생성하는 비용이 크기 때문에 풀에 미리 생성하고 재사용 하는 형태이며, 풀의 크기는 무조건 많다고 좋은 것이 아니라 서버의 성능에 맞게 설정되어야 한다. 무작정 크게 늘리게 되면, 많은 cpu/메모리 사용이 발생하게 되고 이는 다른 문제점을 야기 할 수 있기 때문이다. 일반적은 톰캣의 경우 200개를 기본으로 제공 한다.
만약, 200개의 요청 쓰레드를 사용하고 있는데, 계속 해서 요청이 들어 오게 되면 어떻게 될까? 200개 중 응답을 통해서 반환되는 요청 쓰레드를 획득 하기 까지, 계속 해서 들어오는 요청은 대기 하게 된다. 이러한 요청이 반복된다면, 서버에서는 재시간에 응답을 줄 수 없게 되고, 계속 해서 요청 대기가 발생하게 되고, 계속 해서 요청 지연이 발생 하게 되고, 이러한 현상을 Thread Pool Hell 현상이라고 한다. 최악의 경우 서버의 리소스를 모두 사용하게 되는 문제가 발생 할 수 있다.
WebFlux
WebFlux 동작 원리
Spring WebFlux 는 적은 리소스로 많은 요청을 처리 하기 위해 만들어졌으며, Node.js와 같이 이벤트 기반의 비동기/논블럭킹 방식으로 동작 한다. 즉, 요청이 들어오면 이벤트 루프를 통해서 워커 쓰레드로 넘기게 되며, 워커 쓰레드에서 동작 후 콜백 메서드를 통해서 응답을 반환 하는 구조이다. 이러한 동작 원리를 통해서 많은 사용자의 요청을 처리 할 수 있다. 하지만, 코드 내에 블럭킹 동작이 존재 하게 되면, 블럭킹이 발생되고, WebFlux 의 사용 목적과 다르게 되며, 그 성능을 발휘 하지 못하는 단점이 있다.
Spring WebFlux 특징
- 비동기 및 논 블로킹 처리: I/O 작업에서 블로킹을 피하고, 이벤트 루프를 통해 많은 수의 연결을 동시에 처리할 수 있습니다.
반응형 프로그래밍: 데이터 스트림을 이용한 반응형 프로그래밍을 지원하며, 변화에 대응하는 애플리케이션을 구축할 수 있습니다. - 서버 사이드 이벤트(Server-Sent Events), WebSockets와 같은 실시간 통신을 위한 프로토콜을 지원합니다.
- 어노테이션 기반의 컨트롤러 또는 함수형 라우팅 스타일로 개발할 수 있습니다.
- Spring WebFlux는 주로 비동기 및 실시간 기능이 필요한 웹 애플리케이션, 마이크로서비스 아키텍처, IoT 디바이스와 같이 높은 동시성과 반응성이 필요한 환경에서 사용됩니다.
- Annotated Controllers: 스프링 MVC의 컨트롤러와 유사한 방식으로 어노테이션을 사용하여 요청을 처리하는 방법을 제공합니다.
- Functional Endpoints: 함수형 프로그래밍 스타일로 라우팅 및 요청 처리를 정의할 수 있는 방식입니다. 이 모델은 더 높은 수준의 추상화를 제공하며, 더욱 세밀한 제어와 유연성을 제공합니다.
Spring MVC or WebFlux?
아래 그림은 Spring MVC 와 Spring WebFlux 에서 지원하는 것을 보여 줍니다.
만약 Spring MVC 와 Spring WebFlux 중 어느 것을 선택 할 것인가 고민이면 아래와 케이스를 고려 후 선택 하는 것이 좋습니다.
- 만약, Spring MVC 로 정상적으로 작동한다면, Spring WebFlux로 변경 할 필요가 없습니다. 명령형 프로그래밍은 코드를 쓰고 이해하고 디버깅하는 가장 쉬운 방법입니다. 대부분의 라이브러리는 역사적으로 차단되어 있기 때문에 라이브러리를 최대로 선택할 수 있습니다.
- 이미 차단 기능이 없는 웹 스택을 구입하고 있는 경우 Spring WebFlux는 이 공간의 다른 실행 모델과 동일한 이점을 제공하며 서버(Netty, Tomcat, Jetty, Undertow 및 서블릿 컨테이너), 프로그래밍 모델(주석 컨트롤러 및 기능적 웹 엔드포인트), 반응형 라이브러리(Reactor, RxJava 또는 기타)를 선택할 수 있습니다.
- Java 8 lambdas 또는 Kotlin과 함께 사용하기 위한 가볍고 기능적인 웹 프레임워크에 관심이 있다면 Spring WebFlux 기능적 웹 엔드포인트를 사용할 수 있습니다. 이는 투명성과 제어의 혜택을 받을 수 있는 복잡한 요구 사항이 적은 소규모 애플리케이션 또는 마이크로 서비스에도 좋은 선택이 될 수 있습니다.
- 마이크로서비스 아키텍처에서는 Spring MVC 또는 Spring WebFlux 컨트롤러 또는 Spring WebFlux 기능 엔드포인트를 사용하여 애플리케이션을 혼합할 수 있습니다. 두 프레임워크에서 동일한 주석 기반 프로그래밍 모델을 지원하면 지식을 쉽게 재사용하는 동시에 적절한 작업에 적합한 도구를 선택할 수 있습니다.
- 애플리케이션을 평가하는 간단한 방법은 애플리케이션의 종속성을 확인하는 것입니다. 사용할 차단 지속성 API(JPA, JDBC) 또는 네트워킹 API가 있는 경우 스프링 MVC는 적어도 일반 아키텍처에 대해 최선의 선택입니다. 리액터와 RxJava 모두에서 별도의 스레드에서 차단 호출을 수행하는 것이 기술적으로 가능하지만 차단이 되지 않는 웹 스택을 최대한 활용하지는 못할 것입니다.
- 원격 서비스에 대한 호출이 있는 Spring MVC 애플리케이션이 있는 경우 반응형 웹클라이언트를 사용해 보십시오. Spring MVC 컨트롤러 메서드에서 반응형 유형(반응기, RxJava 또는 기타)을 직접 반환할 수 있습니다. 호출당 지연 시간이 길수록 또는 호출 간의 상호 의존성이 클수록 이점이 극적입니다. Spring MVC 컨트롤러는 다른 반응형 구성 요소도 호출할 수 있습니다.
- 대규모 팀이 있는 경우 비차단, 기능적 및 선언적 프로그래밍으로 전환할 때 가파른 학습 곡선을 염두에 두어야 합니다. 전체 전환 없이 시작할 수 있는 실질적인 방법은 반응형 웹 클라이언트를 사용하는 것입니다. 그 이상으로 소규모로 시작하여 이점을 측정하십시오. 우리는 광범위한 응용 분야에서 전환이 불필요할 것으로 예상합니다. 어떤 이점을 찾아야 할지 잘 모르면 비차단 I/O가 어떻게 작동하는지(예: 단일 스레드 Node.js에서 동시성)와 그 효과에 대해 알아보는 것으로 시작합니다.
-------------
Spring WebFlux 가 동작 할때 기본적으로 사용되는 서버는 Netty를 사용하고 있으며, Reative 스타일의 어플리케이션 개발을 지원하기 위해 Reactor 프로젝트를 사용하고 있습니다. 이번 글에서는 Netty 서버가 무엇인지 간략하게 알아보고, Reactive Stream Publisher 구현체인 Mono 와 Flux 에대해서 간단히 알아보도록 하겠습니다.
Netty는 NIO (Non-blocking IO) 서버 및 클라이언트를 쉽고 바르게 개발 할 수 있는 프레임워크입니다. 빠르고 쉽다는 것은 유지보수나 성능 이슈를 겪는 어플리케이션을 말하지 않습니다. 네티는 FTP, SMTP, HTTP 및 다양한 바이너리 및 텍스트 기반의 프로토콜 구현하여 얻은 경험을 바탕으로 설계 되었고, 그 결과 네티는 개발 용이성, 성능, 언정성 및 유연성을 달성 할 수있는데 성공 했습니다. 라고 네티 공식 문서를 보면 네티를 아래와 같이 정의하고 있으며, 기본 스택은 아래와 같습니다.
즉, Netty는 비동기 이벤트 기반의 어플리케이션 프레임워크이고, 빠르게 서버 및 클라이언트를 개발하고 높은 성능 낼 수 있게 해주는 프레임워크로 보면 됩니다. (더많은 기능에 대해서는 https://netty.io/ 를 참고)