본문으로 건너뛰기

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