본문으로 건너뛰기

1. Spring WebFlux란?​

  • Spring WebFlux는 완전한 논블로킹, 리액티브 스트림 지원을 제공하는 웹 프레임워크입니다.
  • 적은 수의 스레드로 동시성을 처리하고, 더 적은 하드웨어 리소스로 확장할 수 있도록 설계되었습니다.

1.1 탄생 배경​

  • WebFlux의 탄생에는 두 가지 주요 동기가 있습니다:
  • 논블로킹 웹 스택의 필요성
    • 적은 수의 스레드로 동시성 처리
    • 더 적은 하드웨어 리소스로 확장 가능
    • Netty와 같은 비동기, 논블로킹 서버 지원
  • 함수형 프로그래밍의 발전
    • Java 8의 람다 표현식 도입
    • 비동기 로직의 선언적 구성 가능
    • 함수형 웹 엔드포인트 지원

2. 리액티브 프로그래밍 이해하기​

2.1 리액티브의 정의​

리액티브 프로그래밍은 변화에 반응하는 프로그래밍 모델을 의미합니다:

  • 네트워크 컴포넌트가 I/O 이벤트에 반응
  • UI 컨트롤러가 마우스 이벤트에 반응
  • 작업 완료나 데이터 가용성에 대한 알림에 반응

2.2 백프레셔(Back Pressure)​

정보

백프레셔는 데이터 스트림에서 데이터 생산자가 소비자를 압도하지 않도록 제어하는 메커니즘입니다.

  • 동기식 코드: 블로킹 호출이 자연스러운 백프레셔 형성
  • 비동기식 코드: 이벤트 속도 제어가 필수적
  • Reactive Streams: 비동기 컴포넌트 간 상호작용 정의
    • Publisher(생산자)와 Subscriber(소비자) 간의 데이터 흐름 제어
    • Java 9에서 공식 채택

3. Spring WebFlux의 핵심 컴포넌트​

3.1 리액티브 API​

Spring WebFlux는 Reactor를 기본 리액티브 라이브러리로 사용합니다:

  • Mono: 0 또는 1개의 데이터 시퀀스
  • Flux: 0..N개의 데이터 시퀀스
  • ReactiveX 연산자 문법 지원
  • 논블로킹 백프레셔 지원
팁

WebFlux는 Reactor를 코어 의존성으로 사용하지만, RxJava 등 다른 리액티브 라이브러리와도 호환됩니다.

3.2 프로그래밍 모델​

WebFlux는 두 가지 프로그래밍 모델을 제공합니다:

  • 애노테이션 기반 컨트롤러
    • Spring MVC와 동일한 애노테이션 사용
    • 리액티브 타입 반환 지원
    • 리액티브 @RequestBody 인자 지원
  • 함수형 엔드포인트
    • 람다 기반의 경량화된 모델
    • 요청 처리의 완전한 제어
    • 함수형 프로그래밍 스타일

4. 적용 가이드​

4.1 Spring MVC vs WebFlux 선택 기준​

경고

WebFlux 도입을 고려할 때는 다음 사항들을 신중히 검토해야 합니다.

  • 기존 Spring MVC 유지가 좋은 경우:
    • 현재 애플리케이션이 잘 작동 중인 경우
    • 명령형 프로그래밍이 더 익숙한 경우
    • 블로킹 라이브러리를 주로 사용하는 경우
  • WebFlux 도입이 좋은 경우:
    • 논블로킹 웹 스택이 필요한 경우
    • 함수형 프로그래밍 스타일을 선호하는 경우
    • 마이크로서비스 아키텍처에서 일부 서비스만 적용

4. 동시성 모델 이해하기​

  • Spring MVC와 WebFlux는 모두 애노테이션 기반 컨트롤러를 지원하지만, 동시성 모델과 스레드 처리 방식에서 근본적인 차이가 있습니다.

4.1 Spring MVC의 동시성 모델​

정보

Spring MVC는 각 요청당 하나의 스레드를 할당하는 방식을 사용합니다.

  • 스레드 처리 방식:
    • 대규모 스레드 풀 사용
    • 요청마다 새로운 스레드 할당
    • 블로킹 작업 허용 (예: 원격 API 호출, DB 쿼리)
  • 특징:
    • 직관적이고 이해하기 쉬운 코드 작성 가능
    • 동시 요청이 증가하면 스레드 수도 증가
    • 많은 메모리와 컨텍스트 스위칭 비용 발생

4.2 WebFlux의 동시성 모델​

정보

WebFlux는 이벤트 루프 모델을 사용하여 적은 수의 스레드로 많은 요청을 처리합니다.

  • 스레드 처리 방식:
    • 고정된 크기의 작은 스레드 풀 사용
    • 이벤트 루프 워커가 요청 처리
    • 논블로킹 작업과 콜백 기반 처리
  • 특징:
    • CPU 코어 수에 맞춘 스레드 풀 크기
    • 스레드 블로킹이 없어 컨텍스트 스위칭 최소화
    • 콜백 기반의 비동기 프로그래밍 모델

4.3 "적은 스레드로 확장하기"의 의미​

팁

"확장성"과 "적은 수의 스레드"가 모순되어 보일 수 있지만, 이는 WebFlux의 핵심 강점입니다.

  • 논블로킹 방식의 장점:
    • 스레드가 대기 상태에 빠지지 않음
    • 동일 스레드에서 더 많은 요청 처리 가능
    • 메모리 사용량 감소
  • 리소스 활용:
    • 블로킹 작업이 없어 추가 스레드 불필요
    • 콜백 기반으로 비동기 처리
    • CPU 자원 효율적 사용

4.4 블로킹 API 처리​

블로킹 API와 WebFlux의 철학 충돌

WebFlux는 적은 수의 스레드로 높은 동시성을 처리하는 이벤트 루프 모델을 기반으로 합니다. 블로킹 API를 사용해야 하는 경우, Reactor와 RxJava의 publishOn 연산자를 통해 별도 스레드에서 처리할 수 있지만, 이는 다음과 같은 문제를 야기할 수 있습니다:

  • 이벤트 루프 모델의 장점 상실
  • 추가 스레드 생성으로 인한 리소스 낭비
  • 블로킹 작업이 많아질수록 전체 시스템 성능 저하

따라서 WebFlux를 선택할 때는 애플리케이션의 전체 플로우가 논블로킹으로 구성될 수 있는지를 먼저 검토해야 합니다.

5. 적용 가이드 및 서버 지원​

WebFlux는 다양한 서버를 지원합니다:

  • Netty (기본 선택)
  • Tomcat
  • Jetty
  • Undertow
  • 서블릿 컨테이너
정보

Spring Boot WebFlux 스타터는 기본적으로 Netty를 사용합니다. Netty는 비동기, 논블로킹 처리에 최적화되어 있으며, 클라이언트와 서버가 리소스를 공유할 수 있습니다.

6. 마치며​

  • Spring WebFlux는 현대적인 리액티브 프로그래밍 모델을 제공하는 강력한 프레임워크입니다.
  • 적절한 사용 사례를 파악하고, 팀의 학습 곡선을 고려하여 도입을 결정하는 것이 중요합니다.
  • 특히 높은 동시성과 확장성이 필요한 마이크로서비스 아키텍처에서 그 진가를 발휘할 수 있습니다.