-
스프링으로 시작하는 리액티브 프로그래밍 2 - Reactor 알아보기카테고리 없음 2024. 8. 6. 23:30
Chapter 05. Reactor 개요
Reactor 공식 사이트 메인 Reactor 공식 사이트(https://projectreactor.io/)에 들어가면 위와 같이 나온다. 줄이면 리액티브 스트림즈에 기반한 Non-Blocking JVM 어플리케이션이고, 자세히는 아래와 같다.
- Reactive Streams : Reactor는 리액티브 스트림즈(Reactive Streams) 사양을 구현한 리액티브 라이브러리이다. 다른 라이브러리로는 RxJava가 있다.
- Non-Blocking : Reactor는 JVM 위에서 실행되는 Non-Blocking 애플리케이션을 제작하기 위해 필요한 핵심 기술이다.
- Java's functional API : Reactor에서 Publisher와 Subscriber 간의 상호 작용은 Java의 함수형 프로그래밍 API를 통해서 이루어진다.
- Flux[N] : Reactor의 Publisher 타입은 크게 두 가지인데, 그중 하나가 Flux이다. Flux[N]이라는 의미는 N개의 데이터를 emit한다는 것인데, 0개부터 N개, 즉 무한대의 데이터를 emit할 수 있는 Reactor의 Publisher다.
- Mono[0|1] : Mono 역시 Reactor에서 지원하는 Publisher 타입인데, Mono[0|1]과 같이 표현된 이유는 Mono가 데이터를 한 건도 emit하지 않거나 단 한 건만 emit하는 단발성 데이터 emit에 특화된 Publisher이기 때문이다.
- Well-suited for microservices : Non-Blocking I/O 특징을 가지는 Reactor는 마이크로 서비스 기반 시스템에서 수많은 서비스들 간에 지속적으로 발생하는 I/O를 처리하기에 적합한 기술이다.
- Backpressure-ready network : Reactor는 Publisher로부터 전달 받은 데이터를 처리하는 데 있어 과부하가 걸리지 않도록 제어하는 Backpressure를 지원한다.
Chapter 06. 마블 다이어그램(Marble Diagram)
마블 다이어그램은 여러 가지 구슬 모양의 도형으로 구성된 도표로 Reactor에서 지원하는 Operator를 이해하는 데 중요한 역할을 한다. 아래는 마블 다이어그램의 기본 구성을 설명한 그림이다.
마블 다이어그램의 구성 - 다이어그램에는 두 개의 타임라인이 존재하는데, 첫째가 Publisher가 데이터를 emit하는 타임라인이다. 이 Publisher는 데이터 소스를 최초로 emit하는 Publisher일 수도 있고 그렇지 않을 수도 있다. Operator 함수를 기준으로 상위에 있는, 즉 Upstream의 Publisher라고 보는 것이 적절하다.
- Publisher가 emit하는 데이터를 의미한다. 타임라인은 왼쪽에서 오른쪽으로 시간이 흐르는 것을 의미하기 때문에 가장 왼쪽에 있는 1번 구슬이 시간상으로 가장 먼저 emit된 데이터이다.
- 수직으로 된 바는 데이터의 emit이 정상적으로 끝났음을 의미한다. onComplete Signal에 해당한다.
- Operator 함수 쪽으로 들어가는 점선 화살표는 Publisher로부터 emit된 데이터가 Operator 함수의 입력으로 전달되는 것을 의미한다.
- Publisher로부터 전달받은 데이터를 처리하는 Operator 함수이다. Reactor는 굉장히 많은 수의 Operator를 지워ㄴ하며, 각각의 Operator마다 해당 Operator를 잘 설명하는 마블 다이어그램을 가진다.
- Operator 함수에서 나가는 점선 화살표는 Publisher로부터 전달받은 데이터를 가공 처리한 후에 출력으로 내보내는 것을 의미한다. 출력으로 내보낸다는 의미는 정확하게 표현하자면, Operator 함수에서 리턴하는 새로운 Publisher를 이용해 Downstream에 가공된 데이터를 전달하는 것을 의미한다.
- 두번째 타임라인은 Operator 함수에서 가공 처리되어 출력으로 내보내진 데이터의 타임라인이다.
- Operator 함수에서 가공 처리된 데이터를 의미한다.
- 'X' 표시는 에러가 발생해 데이터 처리가 종료되었음을 의미하며, onError Signal에 해당한다.
실제로 Project Reactor 문서 중 Map Operator를 보면 아래와 같이 마블 다이어그램으로 도식화된 것을 확인할 수 있다.
Flux (reactor-core 3.6.8)
projectreactor.io
Chapter 07. Cold Sequence와 Hot Sequence
Cold Sequence는 Subscriber가 구독할 때마다 데이터 흐름이 처음부터 다시 시작되는 Sequence이다. 아래 마블 다이어그램을 보자.
Cold Sequence의 마블 다이어그램 총 두 개의 데이터 처리 흐름인 Sequence를 나타내는 타임라인이 있다. 위쪽에 위치한 Subscriber A가 구독을 하면 Publisher는 네 개의 데이터를 emit한다. 그리고 아래쪽에 위치한 Subscriber B가 구독을 해도 역시 네 개의 데이터를 emit한다. 구독 시점이 다르지만 Subscriber A,B는 모두 동일한 데이터를 전달 받는다. 이처럼 구독 시점이 달라도 구독을 할 때마다 Publisher가 데이터를 emit하는 과정을 처음부터 다시 시작하는 데이터의 흐름을 Cold Sequence라고 부른다.
Hot Sequence의 경우 구독이 발생한 시점 이전에 Publisher로부터 emit된 데이터는 Subscriber가 전달받지 못하고 구독이 발생한 시점 이후에 emit된 데이터만 전달받을 수 있다.
Hot Sequenc 마블 다이어그램 Cold Sequence의 경우 두 번의 구독이 발생하기 때문에 타임라인이 두 번 생성되었는데, Hot Sequence의 경우 세 번의 구독이 발생했지만 타임라인은 하나만 생성되었다. 이 말은 Hot Sequence의 경우 구독이 아무리 많이 발생해도 Publisher가 데이터를 처음부터 emit하지 않는다는 것을 의미한다. Subscriber A는 1번 데이터를 emit하기 전에 구독했기 때문에 1, 3, 5, 7번 데이터를 모두 전달 받는다. Subscriber B는 1, 3번 데이터가 emit된 이후에 구독하여 5, 7번 데이터만 받는다. Subscriber C는 7번 데이터만 받는다.
Chapter 08. Backpressure
Reactor는 아래와 같이 5가지 Backpressure 전략을 제공한다.
종류 설명 IGNORE 전략 Backpressure를 적용하지 않는다. ERROR 전략 Downstream으로 절달할 데이터가 버퍼에 가득 찰 경우, Exception을 발생시키는 전략 DROP 전략 Downstream으로 전달할 데이터가 버퍼에 가득 찰 경우, 버퍼 밖에서 대기하는 먼저 emit된 데이터부터 Drop시키는 전략 LATEST 전략 Downstream으로 전달할 데이터가 버퍼에 가득 찰 경우, 버퍼 밖에서 대기하는 가장 최근에(나중에) emit된 데이터부터 버퍼에 채우는 전략 BUFFER 전략 Downstream으로 전달할 데이터가 버퍼에 가득 찰 경우, 버퍼 안에 있는 데이터부터 Drop시키는 전략 이 중 BUFFER 전략에 대해 조금 더 알아보자.
BUFFER 전략은 버퍼의 데이터를 폐기하지 않고 버퍼링을 하는 전략도 지원하지만, 버퍼가 가득 차면 버퍼 내의 데이터를 폐기하는 전략, 그리고 버퍼가 가득 차면 에러를 발생시키는 전략도 지원한다. 이중 버퍼 내의 데이터를 폐기하는 전략에는 DROP_LATEST 전략과 BUFFER DROP_OLDEST 전략이 있다.
DROP_LATEST 전략은 Publisher가 Downstream으로 전달할 데이터가 버퍼에 가득 찰 경우, 가장 최근에(나중에) 버퍼 안에 채워진 데이터를 Drop하여 폐기한 후, 이렇게 확보된 공간에 emit된 데이터를 채우는 전략이다.
BUFFER DROP_OLDEST 전략은 Publisher가 Downstream으로 전ㄷ잘할 데이터가 버퍼에 가득 찰 경우, 버퍼 안에 채워진 데이터 중에서 가장 오래된 데이터를 Drop하여 폐기한 후, 확보된 공간에 emit된 데이터를 채우는 전략이다.