
Spring Webflux 공식 문서에서 Reactive Streams에 대해 자주 언급됩니다. 그 이유는 Spring Webflux에서 Reactive Streams의 구현체인 Reactor라는 reactive library를 사용하기 때문입니다. Webflux의 동작 구조를 이해하기 위해 Reactive Streams에 대해 알아보고자 합니다.
Reactive Streams?
Reactive Streams는 공식 홈페이지인 reactive-streams.org에서 다음과 같이 정의하고 있습니다.
Reactive Streams is an initiative to provide a standard for asynchronous stream processing with non-blocking back pressure.
Reactive Streams는 논블로킹(Non-blocking) 백 프레셔(back pressure)를 이용한 비동기 스트림 처리의 표준이라고 정의하고 있는데 백 프레셔에 대한 개념이 생소해 아래에서 정리해 보겠습니다.
Back Pressure?
Back Pressure는 빠른 Publisher - 느린 Subscriber 문제를 해결하는 원리입니다.
Reactive Programming 에는 옵저버 패턴(observer pattern) 이 기반 기술로써 사용됩니다. 기존의 옵저버 패턴에서 발생자(publisher)는 구독자(subscriber) 에게 데이터를 밀어 넣는(push) 형태였습니다.

이러한 방식을 push라고 하는데 만약 Publisher가 1초에 10개 밖에 처리가능한 Subscriber에게 더 많은 이벤트를 보내게 된다면 큐(queue)를 이용하여 대기 중인 이벤트를 저장해야 합니다. 추가적으로 계속 push 하게 된다면 한정된 메모리로 인해 오버플로(overflow)가 발생하게 됩니다.

풀(pull) 방식에서는 Subscriber 가 1초에 10개만 처리 가능하다면 publisher에게 10개만 요청합니다. publisher는 요청받은 만큼만 전달하기 때문에 위에서 오버플로우 문제는 걱정하지 않아도 되고 중간에 사용되었던 Queue 도 필요 없어집니다.
추가적으로 subscriber 가 이미 8개의 일을 처리하고 있다면 추가적으로 2개만 더 요청하여 subscriber 가 현재 처리 가능한 범위 내에서만 메시지를 받게 할 수 있습니다. 풀 방식에서는 전달되는 모든 데이터의 크기를 subscriber가 결정하게 되는데 이러한 방식을 dynamic pull이라고 합니다. Publisher의 일방적인 데이터 push가 아니라, dynamic pull 방식의 데이터를 요청해서 subscriber가 수용할 수 있는 만큼만 데이터를 요청하는 방식이 Back Pressure입니다.
Reactive Streams API
Reactive Streams는 아래와 같은 간단한 API들의 조합으로 구성되어 있습니다.
Publisher
public interface Publisher<T> {
public void subscribe(Subscriber<? super T> s);
}
Publisher는 Subscriber를 구독받기 위한 subscribe 메서드가 있습니다.
Subscriber
public interface Subscriber<T> {
public void onSubscribe(Subscription s);
public void onNext(T t);
public void onError(Throwable t);
public void onComplete();
}
Subscriber 에는 받은 데이터를 처리하기 위한 onNext, 에러를 처리하는 onError, 작업 완료 시 사용하는 onComplete, 매개 변수로 Subscription을 받는 onSubscribe 메서드가 있습니다.
Subscription
public interface Subscription {
public void request(long n);
public void cancel();
}
Subscription 은 n 개의 데이터를 요청하기 위한 request와 구독을 취소하기 위한 cancel 메서드가 있습니다.
Reactive Streams API의 흐름은 다음과 같습니다.

- Subscriber 가 subscribe 메서드를 통해 Publisher에게 구독을 요청합니다.
- Publisher는 onSubscribe 메서드로 SubScriber에게 Subscription 전달합니다.
- Subscription은 Subscriber와 Publisher 간 통신의 매개체가 됩니다. Subscriber는 Publisher에게 직접 데이터 요청을 하지 않고, Subscription의 request 함수를 통해 Publisher에게 전달합니다.
- Publisher는 Subscription을 통해 Subscriber의 onNext에 데이터를 전달하고, 작업이 완료되면 onComplete, 에러가 발생하면 onError 시그널을 전달합니다.
- Subscriber와 Publisher, Subscription이 서로 유기적으로 연결되어 통신을 주고받으면서 subscribe부터 onComplete까지 연결되고, 이를 통해 back pressure 가 완성됩니다.
참고
https://pangtrue.tistory.com/191
https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.1/README.md#api-components
https://engineering.linecorp.com/ko/blog/reactive-streams-with-armeria-1/
'Spring > WebFlux' 카테고리의 다른 글
WebFlux 에 대해 알아보자! (0) | 2023.02.26 |
---|