Spring - WebFlux란?
WebFlux는 Spring 5에서 새롭게 추가된 Reactive-Stack의 웹 프레임워크이며, 클라이언트/서버에서 리액티브(reactive) 애플리케이션 개발을 위한 논블로킹 리액티브 스트림을 지원한다.
2017년 8월에 릴리즈되어 Spring5에 새롭개 추가된 WebFlux가 생긴 이유는,
- 적은 양의 스레드와 최소한의 하드웨어 자원으로 동시성을 핸들링 하기 위해 만들어졌다.
- 함수형 프로그래밍 때문이다. Java5에서 RestController나 unit test가 만들어지고, Java8에서 함수형 API를 위한 람다식이 추가됐는데 이는 논블로킹(non-blocking)어플리케이션 API의 토대가 됐다.
WebFlux의 등장
WebFlux는 논블로킹으로 동작하는 웹 스택의 필요성 때문에 등장하게 되었다. 기존 SpringMVC의 Servlet API는 v3.1부터 논블로킹을 위한 API를 제공했었다. 하지만 이외의 동기적으로 처리하는 모듈(Filter, Servlet)과 블로킹 방식의 API(getParameter, getPart)들이 있기에 완벽한 논블로킹 환경의 개발을 할 수 없었으며, 비동기 논블로킹 환경의 서버로 Netty가 부상하고 있었으며 이 Netty와의 연동을 위해 Spring은 새로운 API가 필요했다.
이러한 Spring WebFlux는 아래와 같은 용도로 사용하기를 추천한다고 한다.
- 비동기, non-blocking reactive 개발에 사용하는 경우
- 효율적으로 동작하는 고성능 웹어플리케이션 개발에 사용
- 서비스간 호출이 많은 마이크로서비스 아키텍처에 적합
일반적으로 blocking 코드 작성에는 익숙하기 때문에 생산성이 높을 것이나 non-blocking 코드에는 익숙하지 않고 확실히 이해하고 코딩하지 않으면 알 수 없는 오류도 발생하기 쉽고 디버깅도 어렵기 때문에 학습이 필요하다. 그리고 non-blocking과 blocking코드를 같이 사용하게 되면 비동기 코드가 무의미해지고 성능적인 이점도 볼 수 없기 때문에 고려해야할 부분도 많다.
Spring MVC vs WebFlux
다음은 Spring Mvc와 WebFlux의 차이를 알아보자
Spring MVC와 WebFlux의 공통점은 @Controller, Reactive클라이언트이다. 둘 모두 Tomcat, Jetty, Undertow와 같은 서버에서 실행할 수 있다.
Spring MVC에서는 명령형 논리, JBDC, JPA를 가질수 있고, Spring WebFlux에서는 기능적 엔트 포인트, 이벤트 루프, 동시성 모델을 가질 수 있다.
Spring MVC
Spring MVC는 하나의 요청에 대해 하나의 스레드가 사용된다(thread-per-request). 그래서 다량의 요청을 대비해 미리 스레드 풀을 생성해놓으며, 각 요청마다 스레드를 할당하여 처리한다.
1 request : 1 thread
sync + blocking
WebFlux
리액티브 프로그래밍은 논블로킹과 고정된 스레드 수 만으로 모든 요청을 처리함으로 Spring MVC의 문제들을 해결한다.
서버는 스레드 한 개로 운영하며, 디폴트로 CPU 코어 수 개수의 스레드를 가진 워커 풀을 생성하여 해당 워커 풀 내의 스레드로 모든 요청을 처리한다. 제약이 있다면 논블로킹으로 동작해야만 하며, 블로킹 라이브러리가 필수적으로 사용되어야 한다면, 워커 스레드가 아닌 외부 별도의 스레드로 요청을 처리해야한다. 이는 요청을 처리하는 Event Loop가 절대 블로킹되지 않아야 하기 때문이다.
many request : 1 thread
async + nonblock
WebFlux로 개발하고 DB는 blocking이라면? WebFlux를 쓸 이유가 없다. 라는 개념 아래서 reactive를 지원하는 DB를 사용해야 하는데 우리가 일반적으로 알고있는 RDBMS는 지원하지 않고 Redis, Mongo 등은 지원한다.
WebFlux를 사용하는 이유
배달의민족 기술 블로그를 보면 가게노출 시스템에 WebFlux를 도입하였는데 내용을 보면 가게노출 시스템은 배달의민족 앱 내에서 가장 많은 트래픽을 소화하는 시스템으로, 다음과 같은 리소스 최적화가 반드시 필요하다.
- 하나의 사용자 요청을 처리하기 위해 수십여개의 외부 시스템에 대한 요청이 필요한 시스템에서 어떻게 가장 빠른 응답을 줄 수 있을까?
- 수많은 요청을 처리해야할 때 어떻게 쓰레드 지옥을 벗어날 수 있을까?
앞서서 설명했듯 Spring MVC는 1:1로 요청을 처리하기 때문에 트래픽이 몰리면 많은 쓰레드가 생겨난다. 쓰레드가 전환될 때 문맥교환(context switching) 비용이 발생하게 되는데 쓰레드가 많을수록 비용이 커지기 때문에 적절한 쓰레드 수를 유지해야 하는 문제가 있다.
이에 반해, WebFlux는 Event-Driven 과 Asynchronous Non-blocking I/O를 통해 리소스를 효율적으로 사용할 수 있다로고 만들어 준다.
이렇다고 해서 WebFlux가 무조건 빠르고 좋은 것은 아니다. WebFlux 프로젝트의 비지니스 로직들이 모두 Async + NonBlocking으로 되어있다면 빠를 수 있다. 그런데 이런 코드를 작성하는 것은 어렵다. 그래서 MVC는 못해도 본전이지만 Reactive는 못하면 MVC를 적용하느니만 못한 결과를 가져올 수 있다. 트래픽이 높은 서비스가 아니라면 MVC로도 감당 가능하다.
'Programming > Spring' 카테고리의 다른 글
[Spring] JPA 개념정리 (Hibernate, Spring Data JPA) (0) | 2023.05.08 |
---|---|
DTO, VO, Entity - 개념 정리 및 차이점 (0) | 2023.03.15 |
[Spring] MVC1, MVC2 개념 및 차이점 / Spring MVC 동작과정 (1) | 2022.07.17 |
[Spring] Mybatis - foreach 사용법 및 예제 / 동적 반복 sql 처리 (0) | 2022.06.26 |
[JPA] findBy를 이용한 쿼리 메소드 작성하기(조건처리, like구문 처리) (0) | 2022.02.02 |