WebFlux의 개념과 사용법

2024. 2. 19. 17:29


0. 목차

  1. WebFlux, 넌 누구냐
  2. Reactive Programming
  3. WebFlux 개념
    1. WebFlux란?
    2. WebFlux의 등장 배경
    3. WebFlux 사용의 권장되는 환경
    4. WebFlux가 무조건 좋은가?
    5. Spring MVC vs WebFlux
  4. Mono vs Flux

1. WebFlux, 넌 누구냐


2024년부터 팀원분과 새로운 프로젝트를 진행하게 됐다.
이미 어느정도 기본 셋팅이 이루어진 프로젝트였는데, 이 프로젝트에서는 WebFlux로 외부 API를 호출하고 있었다.

WebFlux는 들어만봤지 실제로는 사용한 적이 없었는데, 대략적으로 전통적인 Spring MVC에 비해 스레드를 상대적으로 덜 사용한다 정도까지만 알고 있었다.

제대로 사용하기 전에 왜 이 프로젝트에서는 WebFlux를 사용했는지, Spring MVC에 비해 상대적으로 어떤 장단점을 가지고 있는지 알고가면 좋겠다는 생각이 들어서 이 글을 정리해본다.


2. Reactive Programming


Reactive Programming 이라고하면 보통은 아래 4가지를 준수한다.

  1. 성능과 확장성
    • 비동기적으로 동작하고, 병렬성을 통해 성능과 확장성을 향상
    • 다수의 이벤트를 동시에 처리할 수 있으며, 필요에 따라 시스템을 확장
  2. 반응성과 사용자 경험
    • 리액티브 시스템은 실시간으로 데이터 변화에 반응하여 빠른 응답을 제공
    • 이용자 경험을 향상시키는데 도움이 됨
  3. 장애 처리와 회복력
    • 장애가 발생하더라도 탄력적으로 대응 가능
    • 오류를 격리시키고, 다른 컴포넌트에 영향을 주지 않으면서 정상 동작을 유지

말로만 봐서는 한 번에 이해가 안되는데, 코드에서 예시를 찾아보자.


기존의 명령형 프로그래밍

var string = 'THis is the midday show with Cheryl Waters';
var urlFriendly = "";

for(var i=0; i<string.length; i++){
    if (string[i] === " ") {

        urlFriendly += "-";

    } else {

        urlFriendly += string[i];

    }
}

console.log(urlFriendly);

새로운 패러다임, 선언적 프로그래밍

const string = 'This is the midday show with Cheryl Waters';
const urlFriendly = string.replace(/ /g, '-');

console.log(urlFriendly);

보다시피 선언적 프로그래밍에서는 구체적인 절차 대신 replace라는 함수를 사용해 추상적인 개념을 표현한다.
선언적 프로그래밍의 코드 구문에서는 어떤 일이 발생해야 하는지 기술하고, 실제로 그 작업을 처리하는 방법은 추상화로 아랫단에 감추어진다.


코드만 보자면 Java 8버전부터 제공된 Lambda의 간결함이 떠오르는데, 결론적으로 Reactive Programming에 대해서 아래와 같이 요약을 정리했고, 이러한 특징들로 인해 자원을 보다 효율적으로 활용하고 동시다발적인 이벤트를 빠르게 처리하는 것이 가능하다는 특징을 이해했다.


  • 비동기 (Asynchronous)
  • 논 블록킹 (Non-Blocking)

참고로 동기와 비동기, 블록킹과 논 블로킹의 개념은 서로 비슷하면서도 다른데, 간략하게 요약하자면 아래와 같은 특징들이 있다.


  • 동기 & 비동기 : 리턴 값을 확인 유무로 구분
    • 동기 : 리턴 값을 기다리거나, 완료가 안되고 리턴 값을 받더라도 작업 완료 여부를 계속 확인
    • 비동기 : 리턴 값을 신경쓰지 않고 따로 동작
  • 블로킹 & 논 블로킹 : 제어권의 주체를 넘기느냐 안 넘기느냐의 구분
    • 블로킹 : 제어권을 넘기고 제어권을 다시 돌려받을 때까지 기다렸다가 돌려받고 동작을 시작
    • 논블로킹 : 제어권을 넘기지 않고 동작

디테일한 내용이 궁금하다면 다른 개발자분이 작성한 동기와 비동기 / 블로킹과 논블로킹 - Click을 참고하자.


3. WebFlux 개념


(1) WebFlux란?

  • Spring 5에서 새롭게 추가된 Reactvie-Stack의 웹 프레임워크
  • SpringBoot2.0 부터 사용 가능
  • Reactive Application 개발을 위한 논 블록킹 리액티브 스트림을 지원

(2) WebFlux의 등장 배경

  • 적은 양의 스레드로 동시성 이슈를 해결하기 위한 논 블록킹 웹스택의 필요성으로 인해 등장
  • 비동기 논블로킹 환경의 서버 Netty가 부상하고 있었으며, Netty와의 연동을 위해 Srping은 새로운 API가 필요했음
  • 기존 SpringMVCdml Servlet API는 v3.1부터 논블로킹을 위한 API를 제공해왔지만, 동기적으로 처리하는 모듈(Filter, Servlet)과 블로킹 방식의 API(getParameter, getPart)들이 있기에 완벽한 논블로킹 환경의 개발을 할 수 었었음

(3) WebFlux가 권장되는 환경

  • 비동기, non-blocking service 개발에 사용하는 경우
  • 효율적으로 동작하는 고성능 웹어플리케이션 개발에 사용
  • 서비스간 호출이 많은 MSA에 적합
  • NoSQL을 사용하는 환경
    • WebFlux로 개발하고 DB가 blocking이라면 WebFlux를 쓸 필요가 없음
    • Reactive를 지원하는 DB를 사용해야 하는데, 일반적으로 RDBMS는 지원하지 않고 Redis, MongoDB 등을 지원

(4) WebFlux가 무조건 좋은가?

  • 프로젝트의 비즈니스 로직이 모두 비동기 + 논블로킹으로 동작한다면 빠를 수 있음
    • 그러나 현실적으로 이런 프로젝트를 구성하기는 쉽지 않음
  • MVC는 못해도 본전이지만, Reactive는 못하면 MVC를 적용하느니만 못한 결과를 가져올 수 있음
  • 트래픽이 높은 서비스가 아니라면 MVC로도 충분히 감당 가능

(5) Spring MVC vs WebFlux

  • SpringMVC : 하나의 요청에 하나의 스레드 사용. 따라서 다량의 요청에 대비해 미리 스레드 풀을 생성
    • 1 Request : 1 Thread
    • 동기 + 블로킹
  • WebFlux : 논블로킹 + 고정된 스레드 수 만으로 요청을 처리하여 Spring MVC의 문제점을 해결
    • Many Requests : 1 Thread
    • 비동기 + 논블로킹
    • 서버는 스레드 1개로 운영, 디폴트로 CPU 코어 수 개수의 스레드를 가진 워커 풀을 생성하여 해당 풀 내의 스레드로 모든 요청을 처리
    • 단, 논블로킹으로 동작해야만 하며, 블로킹 라이브러리가 필수적으로 사용되어야한다면 워커 프로세스가 아닌 별도의 스레드로 요청해야 함
      • 요청을 처리하는 EventLoop가 절대로 블로킹되지 않아야 하기 때문

(6) Mono vs Flux

Spring Webflux에서 사용하는 reactive libraryReactor이고, ReactorReactive Strems의 구현체이다.
FluxMonoReactor 객체 이며, 차이점은 발행하는 데이터 개수이다.


  • Mono : 0 ~ 1개의 데이터 전달
  • Flux : 0 ~ N개의 데이터 전달

보통 여러 스트림을 하나의 결과로 모아줄 때 Mono를, 각각의 Mono를 합쳐서 한 번에 여러개의 값을 전달할 때는 Flux를 사용한다.
그런데 Flux도 0 ~ 1개의 데이터를 전달하는게 가능한데, 굳이 한 개 까지만 데이터를 처리할 수 있는 Mono 타입이 왜 필요한걸까?


이는 데이터 설계시, 결과가 없거나 하나의 결과값만 받는 것이 명백할 경우 굳이 List나 배열을 사용하지 않는 것 처럼, Multi Result가 아닌 하나의 결과값만 받게 될 경우 불필요하게 Flux를 사용하지 않고 Mono를 사용하면 되기 때문이다.



참고 자료 (Click)