포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.

 

 

강의 요약

오늘 강의에서는 리액티브 프로그래밍의 기초 이론을 학습했다. 특히 Reactive Streams 표준과 Project Reactor 라이브러리가 무엇이고,  스트림에 대한 구성요소, 비동기 프로그래밍의 메커니즘에 대해 알 수 있었다. 해당 내용들을 간단하게 정리해보자.

 

Reactive Streams의 필요성

전통적인 동기 방식 시스템에서는 데이터 생산자가 소비자의 처리 속도를 고려하지 않고 데이터를 전송하면 메모리 부족이나 시스템 과부하가 발생할 수 있다. 특히 스트리밍 데이터처럼 데이터 양이 미리 정해지지 않은 경우 이러한 문제가 더욱 심각해진다.

Reactive Streams는 비동기 스트림 처리를 위한 표준 명세로, 논블로킹 백프레셔를 필수 요소로 정의한다. 이를 통해 스레드 간 데이터 교환 시 수신 측이 임의의 양의 데이터를 버퍼링하도록 강제되지 않으며, 처리 가능한 만큼만 요청하는 방식으로 시스템 안정성을 보장한다.

 

비동기 스트림 처리의 핵심 개념

Reactive Streams는 다음과 같은 특성을 가진 스트림 처리를 목표로 한다.

  • 잠재적으로 무한한 수의 요소 처리
  • 순차적 처리
  • 컴포넌트 간 비동기 요소 전달
  • 필수적인 논블로킹 백프레셔

비동기 처리의 이점은 여러 CPU 코어나 네트워크 호스트 간 병렬 처리를 가능하게 한다는 점이다. 하지만 백프레셔 신호가 동기적으로 동작한다면 이러한 이점이 상쇄되므로, 명세는 모든 측면에서 완전히 논블로킹하고 비동기적인 동작을 강제한다.

 

Non-blocking Backpressure의 동작 원리

백프레셔는 빠른 데이터 소스가 스트림 목적지를 압도하지 않도록 리소스 소비를 제어하는 메커니즘이다. Reactive Streams에서 백프레셔는 구독자가 요청한 요소의 총 개수를 추적함으로써 구현된다. 구독자는 항상 다음 정보를 알고 있다.

  • 요청한 총 요소 수 (P)
  • 처리 완료한 요소 수 (N)
  • 입력 버퍼의 요소 수 (B)

이를 통해 발행자가 보낼 수 있는 최대 요소 수는 P - B - N으로 제한된다. 발행자는 소스의 생산 속도를 제어할 수 있는지와 무관하게 이러한 경계를 준수해야 한다. 생산 속도를 제어할 수 없는 소스의 경우 버퍼링이나 드롭 방식으로 경계를 지켜야 한다.

구독자가 하나의 요소를 수신한 후 다음 요소를 요청하는 방식은 Stop-and-Wait 프로토콜과 유사하며, 여러 요소를 한 번에 요청하면 확인 비용을 분산시킬 수 있다. 구독자는 언제든지 수요를 신호할 수 있어 불필요한 지연 없이 입력 버퍼를 채울 수 있다.

 

Reactive Streams API 구성 요소

Reactive Streams API는 네 가지 핵심 인터페이스로 구성된다.

 

Publisher

onSubscribe onNext* (onError | onComplete)?
  • 발행자는 잠재적으로 무한한 수의 순차적 요소를 제공하며, 구독자의 수요에 따라 발행한다.
  • Publisher.subscribe(Subscriber) 호출에 대한 응답으로 다음 프로토콜이 실행된다.
  • 이는 항상 onSubscribe가 먼저 신호되고, 이후 구독자가 요청한 만큼 onNext가 신호되며, 마지막으로 onError 또는 onComplete로 종료됨을 의미한다.

 

Subscriber

  • 구독자는 Subscription.request(long n)을 통해 수요를 신호해야 onNext 신호를 받을 수 있다.
  • 신호 처리가 발행자의 응답성에 부정적 영향을 줄 것으로 예상되면 비동기적으로 신호를 처리하는 것이 권장된다.

 

Subscription

  • 구독은 발행자와 구독자 간 데이터 교환을 중재하는 역할을 한다.
  • request(long n) 메서드는 재진입 가능해야 하며, 상호 재귀로 인한 스택 오버플로를 방지하기 위해 재귀 깊이에 상한선을 두어야 한다.
  • cancel() 메서드는 멱등성과 스레드 안전성을 보장해야 한다.

 

Processor

  • 프로세서는 구독자이자 발행자인 처리 단계를 나타낸다.
  • 두 인터페이스의 계약을 모두 준수해야 하며, onError 신호를 복구하도록 선택할 수 있다.
  • 복구하지 않는 경우 즉시 구독자에게 전파해야 한다.

 

Project Reactor의 핵심 타입

Project Reactor는 Reactive Streams 명세를 구현한 라이브러리로, Spring WebFlux의 기반이 된다. 두 가지 핵심 타입을 제공한다.

 

Mono와 Flux의 선택 기준

타입 요소 수 사용 사례 유사 개념
Mono 0 또는 1 단일 값 반환 작업 (ID 조회, 리소스 생성) Optional, Future
Flux 0 부터 N 다중 값 반환 작업 (컬렉션 조회, 스트리밍) Stream, Collection
  • Mono는 최대 하나의 항목을 방출한 후 완료되거나 즉시 완료된다.
  • Flux는 임의의 수의 항목을 방출할 수 있으며 무한 스트림도 지원한다. 두 타입 모두 변환, 필터링, 오류 처리를 위한 동일한 연산자 세트를 제공한다.

 

동기 처리와 비동기 처리의 조합

Reactive Streams API는 모든 요소 처리가 발행자를 블로킹하지 않아야 한다고 규정하지만, 각 핸들러는 이벤트를 동기적 또는 비동기적으로 처리할 수 있다. 파이프라인의 각 단계에서 비동기 경계를 설정할지, 동일 스레드에서 동기 처리할지 선택할 수 있다.

 

참고 출처

 

 

 

 

 

 

 

시작 시간
종료 시간
학습 인증 - 노션 필기

 

 

https://fastcampus.info/4oKQD6b

+ Recent posts