Page tree
Skip to end of metadata
Go to start of metadata

Introduction

이 글은 spring.io의 블로그에 개재된 Notes on Reactive Programming Part I: The Reactive Landscape의 번역글로, 리액티브 프로그래밍에 대한 전반적인 배경을 다루고 있습니다. 이 글을 시작으로, 리액티브 프로그래밍에 대한 다양한 주제와 실제적인 예제에 대해 다뤄보고, 리액티브 프로그래밍의 전망(?)에 대해서 살펴보도록 하겠습니다.

Prerequisite

이 글을 읽기 위해 다음과 같은 몇 가지 사전 지식이 필요합니다.

  • 객체 지향 프로그래밍(Object Oriented Programming)
  • 함수형 프로그래밍(Functional Programming)
  • 람다식(Lambda Expression)
  • JSDK 8

 

서론

 

리액티브 프로그래밍은 흥미로운 (또다른) 하나의 프로그래밍 기법으로, 현재 시점에서 이에 대한 설왕설래가 많은 것도 사실이다. 리액티브 프로그래밍의 개념 중 일부는 외부인들이나 필자와 같은 보통의 자바 엔터프라이즈 개발자들이 보기에 매우 쉽지만도 않다. 이글은 (이와 관련된 시리즈의 첫 번째 글로) 도대체 무엇 때문에 이 소란인지 이해할 수 있도록 하기 위해 쓰여졌다. 가능한한 구체적인 접근방법을 이용할 것이고, 소위 "표시적 의미론(denotational semantics)"에 대해 언급하지 않을 것이다. 만약 당신이 좀 학구적인 내용을 알고 싶다거나, 하스켈 언어로 작성된 수많은 코드 샘플들을 찾고 있다면 이 글을 적합한 글이 아닐 것이다. 인터넷에 있는 수많은 다른 글을 참고하라.

리액티브 프로그래밍은 종종 동시성 프로그래밍(concurrent programming)나 고성능 처리 등과 떼어놓기 어려울 정도로 같이 언급되긴 하지만, 사실 이들은 원론적으로 완전히 다르다. 이것이 필연적인 혼란을 야기한다. 또, 리액티브 프로그래밍은 함수형 반응형 프로그래밍(Functional Reactive Programming, FRP)와 같이 언급되기도 하고 같은 것으로 여겨지기도 한다.(여기서는 이 두 가지가 상호교환이 가능하다고 간주한다.) 어떤 사람들은 리액티브이라는 것은 전혀 새롭지 않고, 어쨌든 지금껏 계속 해 왔던 것이라 생각하기도 한다.(그들의 대부분은 자바스크립트를 사용했던 사람들이다.) 또 다른 사람들은 이것이 Microsoft가 전해준 선물이라고 생각하기도 한다.(Microsoft는 얼마 전 C#의 확장기능을 배포하면서 매우 큰 파장을 일으켰었다.) 엔터프라이즈 자바의 영역에서는 최근 상당한 소란이 있었고 (Reactive Streams initiative를 참고하라), 뭔가 대단하고 새롭다는 생각으로 인해, 이 기술이 언제 어디에 사용되어야 하는지 제대로 알지 못해 발생한 단순한 오해가 많았던 것도 사실이다.


 

무엇인가?

 

리액티브 프로그래밍은 지능적 라우팅과 이벤트 소비에 대한, 그리고 이들 모두를 합쳐 행동을 변화시킨다는 마이크로 아키텍쳐 스타일이다. 좀 추상적으로 들리는데, 온라인에서 얻을 수 있는 다른 수많은 정의들도 역시 다소 추상적이다. 우리는 여기서 리액티브라는 것이 의미하는 바에 대해 보다 구체적인 개념을 세워볼 것이고, 그 다음으로 이것이 왜 중요할 수 있는지에 대해서도 다룰 것이다.

리액티브 프로그래밍의 기원은 1970년대, 혹은 그보다도 이전으로 거슬러 올라갈 수 있을 듯 한데, 그 말은 개념적으로 새로울 것은 없다는 말이기도 하다. 하지만 이것이 현대 엔터프라이즈 환경에 어떤 큰 반향을 주고 있는 것도 사실이다. 리액티브 프로그래밍이 주는 반향은 마이크로서비스의 부흥, 그리고 멀티코어 프로세서의 대중화와 (필연적으로) 동시에 이루어졌다. 그렇게 된 몇몇 이유들을 이 글에서 다룰 것이다.

다른 곳에서 언급된 유용하면서도 간략한 정의들을 들어보면 다음과 같다.

리액티브 프로그래밍을 뒷받침하는 기본적인 개념은 어떤 값에 지속적으로 대응할 수 있는 어떤 데이터 타입들이 있다는 것이다. 
이런 지속적으로 변화하는 값들과 연관된 연산 작업들은 연산 자체가 지속적으로 변화하는 값을 갖고 있게 된다.

또, 다음과 같은 내용도 있다.

리액티브 프로그래밍이 무엇인지에 대해 직관적으로 이해할 수 있는 가장 쉬운 방법은 
당신이 작성하고 있는 프로그램이 스프레드시트(Spreadsheet) 프로그램이고 
당신이 갖고 있는 모든 값들이 스프레드시트 내의 셀(Cell)이라고 생각하는 것이다. 
스프레드시트 내의 셀이 하나라도 변경되면 그 셀과 관련된 모든 셀들이 같이 변경된다. 
이것은 FRP(함수형 반응형 프로그래밍)에서도 마찬가지이다. 
이제 몇몇 셀들이 스스로 변화한다고 생각해보자.(혹은 외부 세계로부터 변화가 전달되었다고 생각할 수도 있다.): 
GUI 프로그램을 생각하면 마우스 포인터의 위치가 좋은 예가 될 수 있을 것이다.

(Stackoverflow에 언급된 용어에 대한 질문으로 부터 발췌)

함수형 반응형 프로그래밍(FRP)은 고성능, 동시성, 비동기 처리, 그리고 넌블러킹 IO 등의 개념과 매우 친밀하다. 하지만, FRP가 그런 것들과 아무런 관계가 없는 것은 아닌가라는 의심을 갖고 시작하는 것이 도움이 될 수도 있다. 분명히 리액티브 모델(Reactive Model)을 사용하면 그러한 고려사항들이 (종종 호출자의 입장에서는 당연스러울 정도로) 자연스럽게 처리되기도 한다. 하지만 리액티브 프로그래밍의 진정한 혜택은, 이러한 고려사항들을 효과적이고 효율적으로 처리할 수 있다는 점에서, 전적으로 구현에 관련된 문제라고 생각할 수 있다.(그러므로 이 부분에 대해 매우 면밀히 살펴봐야 한다.) 완벽히 적절하고 유용한 FRP 프레임워크를 동기식(synchronous)으로, 그리고 단일 스레드 방식으로 구현하는 것이 가능하긴 하지만, 이는 FRP와 관련된 새로운 도구와 라이브러리들을 사용하는 데에 그리 도움이 되지 않는다.


 

리액티브 사용 사례

 

새로 시작하는 개발자들이 대답을 듣기 어려운 질문은 "그래서 뭐가 좋다는 거야?"일 것이다. 이제 몇 가지 엔터프라이즈 환경에서의 일반적인 사용 패턴을 살펴보자.

 

외부 서비스 호출(External Service Call)

요즘의 많은 백엔드 서비스들은 REST 방식(즉 HTTP 기반으로 동작한다)이며 그래서 기반 프로토콜은 기본적으로 응답을 대기(blocking)해야 하고 동기적(synchronous)으로 수행된다. 여기에 FRP가 비빌 언덕이 없어보이지만, 사실 이 지점이야말로 FRP가 적용될 수 있는 부분이다. 그 이유는 이런 서비스들은 또 다른 서비스들을 호출하도록 구현되며, 그래서 수많은 서비스들이 첫 번째 호출의 결과와 관련있기 때문이다. 수많은 입출력(IO)가 수행되는 과정에서, 만약 어떤 요청을 전송하기 전에 다른 호출이 완료되기를 기다려야 한다면, 서비스 사용자는 응답 데이터가 만들어지기도 전에 좌절하여 포기할 수도 있다. 그렇기 때문에 외부 서비스를 호출하는 경우, 특히 그 서비스 호출들이 복잡하게 연결되어 있는 경우야 말로 최적화하기 좋은 지점이 된다. FRP는 이러한 동작들을 수행하는 로직을 조합할 수 있도록 보장하며, 그래서 개발자들은 서비스를 호출하는 코드를 쉽게 작성할 수 있다. 

 

높은 동시성 메세지 소비자(Highly Concurrent Message Consumers)

메세지 프로세싱은, 특히 고도의 동시 처리를 수행한다는 점에서 엔터프라이즈 어플리케이션에서 흔히 사용된다. 리액티브 프레임워크들은 마이크로 벤치마크를 측정하여 JVM 내에서 1초당 수없이 많은 메세지를 처리할 수 있는지 보여주기를 좋아한다. 벤치마크 결과는 믿기 어려울 정도로 놀라운데(초당 수천만 메세지들이 쉽사리 처리된다), 사실 다소 인위적인 결과일 수 있다. - 벤치마크 테스트를 위해 단순한 for 반복문을 사용했다고 한다면 그다지 감동적이지 않을 것이기 때문이다. 그렇다고 해서 이런 시도를 섣불리 그만둬서는 안 되는데, 성능이 문제가 되는 경우는 흔하며 그런 경우 (성능 향상을 위한) 모든 기여는 감사히 받아들여지기 때문이다. 리액티브 패턴들은 (이벤트가 멋지게 메세지로 번역되기 때문에) 메세지 프로세싱과 자연스럽게 들어맞으며, 그래서 보다 많은 메세지들을 처리하는 방법이 있기만 하다면 주의를 기울일 필요가 있다.

 

스프레드시트(SpreadSheet)

스프레드시트는 엔터프라이즈 어플리케이션은 아니지만, 엔터프라이즈 환경에서 일하는 모든 사람들은 이에 관련되어 있고, FRP의 철학과 FRP 구현의 어려움을 잘 이해하는 데에 도움을 준다. 만약 B셀이 A셀에 의존하고 있고, C셀이 A셀과 B셀 모두에 영향을 받는 상황을 생각해보자. 어떻게 하면 어떤 변화 이벤트도 B에 전달되기 전에 C가 갱신될 것을 보장하면서 A의 변화를 전파할 수 있을까? 만약 당신이 사용하는 프레임워크가 매우 액티브하다면 단순히 "걱정할 필요 없다. 그저 의존관계를 선언하기만 하면 된다."라고 말할 것이고, 이것이 바로 요컨대 스프레드시트 프로그램의 진정한 힘일 것이다. 이 부분이 FRP와 단순한 이벤트 드리븐 프로그래밍의 차이를 보여주는 것이라 할 수 있다. - FRP는 "지능형 라우팅(intelligent routing)"에 지능을 부여한다.

 

(비)동기 처리에 대한 추상화(Abstraction Over (A)synchronous Processing)

이것은 다소 추상적인 사용예이고, 그래서 피해야 할 영역에 들어서는 것이 수도 있다. 여기에는 지금까지 언급했던 내용들과 (매우 많이) 겹치는 부분이 있지만, 그래도 다뤄볼 만 할 것이다. 첫 번째 내용은 친숙한 (그리고 타당한) 것인데, 개발자들이 추가적인 추상 계층을 받아들일 수만 있다면, 자신이 호출하는 코드가 동기적이든 비동기적이든 신경쓰지 않아도 된다는 것이다. 비동기 프로그래밍을 다룬다는 것이 뇌에 과부하를 주는 것이기 때문에 이런 발상은 꽤 유용하다고 할 수 있다. 리액티브 프로그래밍이 이런 이슈를 해결하는 유일한 방법은 아니지만, FRP의 구현자들은 그들이 만든 도구들이 유용할 수 있도록 이에 대해 충분히 고려해왔다.

넷플릭스 블로그에는 실제로 적용할 만한 유용하고 구체적인 예들이 다뤄져 있다: Netflix Tech Blog: Functional Reactive in the Netflix API with RxJava


 

비교

 

당신이 1970년부터 동굴에 살다 나온 것이 아니라면, 리액티브 프로그래밍과 연관된 다른 개념들에 대해, 그리고 사람들이 해결했거나 노력했던 문제들에 대해 접해본 적이 있을 것이다. 아래에 내 개인적인 선택으로 관련성이 높은 것들을 추려보았다.

 

Ruby 이벤트 머신(Ruby Event-Machine)

이벤트 머신은 (일반적으로 넌블럭킹 IO와 관련있는) 동시성 프로그래밍에 대한 추상화이다. Ruby 언어의 개발자들은 단일 스레드 스크립팅 방식으로 설계된 언어를, 1. 제대로 동작하고, 2. 성능이 좋으며, 3. 고부하 상황에서도 지속적으로 동작하는, 그러한 서버 어플리케이션을 작성할 수는 언어로 변경하기 위해 오랜 시간 악전고투를 해왔다. Ruby 언어에는 꽤 오랜 기간 스레드가 있었지만, 그리 많이 사용되지 않았고 그다지 성능이 좋지 않았기 때문에 좋은 평가를 받지 못해왔었다. 그 대안으로 받아들여진 것은 (Ruby 1.9부터) 코어 언어에 추가되어 이제는 당연히 사용되고 있는 Fibers(sic)이다. Fiber 프로그래밍 모델은 coroutine(아래에서 다룰 것이다)의 일종이라고 할 수 있는데, 여기서는 수많은 (IO와 관련된) 동시 요청들을 처리하기 위해 단일 네이티브 스레드가 사용된다. 이 프로그래밍 모델은 다소 추상적이고 이해하기 어려운 면이 있기 때문에 대부분의 사람들은 래퍼(wrapper)를 이용하는데, 이를 위해 일반적으로 이벤트 머신이 가장 많이 사용된다. 이벤트 머신이 반드시 Fiber를 사용해야 하는 것은 아니지만 (이런 고려사항들이 추상화되어 있다), Ruby 웹 앱에서 Fiber와 같이 이벤트 머신을 사용하는 예제 코드를 찾기는 결코 어려운 일이 아니다.(예를 들어, Ilya Grigorik의 글이나 em-http-request의 fiber 예제가 있다.) 사람들은, 높은 I/O를 유발하는 어플리케이션에서 수많은 중첩 콜백(nested callback)을 이용해야 하는 추한 프로그래밍 모델 대신, 확장성(scalability)의 혜택을 얻기 위해 이벤트 머신을 자주 사용한다. 


액터 모델(Actor Model)

객체 지향 프로그래밍과 비슷하게, 액터 모델은 1970년대로 거슬러 올라가야 할 만큼 컴퓨터 과학에서 역사가 길다. 액터들은 자연스러운 결과로 동시성을 허용하는 연산(computation)에 대해 (데이터와 행동과는 달리) 추상화를 제공하는데, 그래서 그들은 실용적인 측면에서 동시성 시스템의 기초를 마련할 수 있었다. 액터들은 각각의 메세지들을 발송하는데, 그렇기 때문에 어떤 의미에서 리액티브이라고 할 수 있으며, 결과적으로 액터 혹은 리액티브 스타일로 구성된 시스템들 사이에는 매우 많은 공통점이 있다. 결과적으로 차이점은 구현 수준에 있다고 할 수 있다.(예를 들어 Akka의 액터들은 여러 프로세스로 분산될 수 있는데 이것은 이 프레임워크의 독특한 특징이다.)

 

지연된 결과 (Deferred results) (Futures)

Java 1.5는 Doug Lea의 java.util.concurrent를 포함하는 풍부하고 새로운 라이브러리 셋을 제시했는데, 그 중에 Future 인터페이스에 지연된 결과의 개념이 캡슐화되어 포함되어 있다. 이것은 비동기 패턴에 대한 단순한 추상화의 좋은 예라 할 수 있는데, 구현이 반드시 비동기적이어야 하는 것도 아니고 특정한 비동기 처리 모델을 사용해야 하는 것도 아니다. 넷플릭스 테크 블로그의 Functional Reactive in the Netflix API with RxJava에 잘 설명되어 있듯이, Future는 비슷한 작업 군에 대해 동시성 처리를 해야할 때 매우 좋긴 하지만, 곧 그들이 서로 의존하게 되거나 조건부로 실행되어야 하는 경우 중첩 콜백의 지옥(nested callback hell)에 빠질 수 있다. 리액티브 프로그래밍이 이 문제에 대한 해답이 될 수 있다.


맵-리듀스와 포크-조인 (Map-reduce and fork-join) 

병렬 처리에 대한 추상화는 유용하며 그에 대해 선택할 만한 예제들이 도처에 널려있다. 맵-리듀스와 포크-조인은 Java 세계에서 비교적 최근에 진전되었는데, 이는 대규모 병렬 분산 처리(MapReduce와 Hadoop)와 JDK 1.7(Fork-Join)에 의해 이루어졌다. 이들은 매우 유용하긴 하지만, (지연된 결과와 비슷하게) FRP와 비교하면 다소 얕다(shallow)고 할 수 있다.. FRP도 단순한 병렬 처리를 위한 추상화 구조로서 사용될 수 있지만, 그것을 넘어 조합성(composability)와 선언적 통신(declaritive communication)에까지 이를 수 있다.


코루틴 (Coroutines) 

"코루틴(coroutine)"은 서브루틴(subroutine)의 일반화이다.  - 진입점(entry point)와 종료점(exit point)이 있다는 점에서 서브루틴과 비슷하지만, 종료될 때 (꼭 자신의 호출자에게가 아니라) 다른 코루틴에 제어를 넘기고, 그동안 축적해 둔 어떤 상태든 저장되어 다음 호출때까지 기억된다. 코루틴은 액터나 스트림(Stream)과 같은 고수준 기능을 위한 유용한 빌딩블럭으로 사용될 수 있다. 다양한 종류의 코루틴들이 있는데, 그들 중 몇몇은 일반적인 경우보다 좀 더 제한적이지만 순수한 서브루틴들 보다는 더 유연하다. (이벤트 머신에서 다뤘던) Fiber가 이것의 하나이고, (스칼라와 파이선에서 친숙한) 제너레이터(Generator)도 이 종류이다.


 

Java에서의 리액티브 프로그래밍

 

Java는 언어 자체가 코루틴을 지원하지 않는다는 점에서 "리액티브 언어"는 아니다. JVM에도 리액티브 모델을 자체적으로 지원하는 (스칼라나 클로저(Clojure)와 같은) 언어들이 있긴 하지만, Java 자체는 버전 9가 되기 전에는 리액티브 언어라고는 할 수 없을 것이다. 하지만 Java는 엔터프라이즈 개발에서 주력으로 사용되는 언어이고, 그래서 최근 JDK 위에서 리액티브 계층(reactive layer)를 제공하기 위한 수많은 활동이 있어왔다. 여기서 이들 중 몇몇에 대해 간략히 살펴볼 것이다.

 

Reactive Streams 

Reactive Stream은 매우 낮은 수준의 계약으로, 몇 안되는 Java 인터페이스(와 Technology Compatibility Kit)로 표현되지만, 다른 언어에도 적용될 수 있다. 이 인터페이스들은 명시적인 배압(back pressure)과 함께 배포자(Publisher)와 구독자(Subscriber)를 위한 기본적인 빌딩 블럭을 표현하는데, 상호 정보교환을 하는 라이브러리들을 위한 일반적인 언어를 만든다. Reactive Stream은 JDK 버전 9의 java.util.concurrent.Flow에 통합되었다. 이 프로젝트는 Kaazing, 넷플릭스, 피보탈, 레드햇, 트위터, Typesafe, 그리고 그 외의 다양한 기업의 엔지니어들이 공동참여하고 있다.


RxJava

넷플릭스는 꽤 오랜기간동안 리액티브 패턴을 사용해왔으며, 이후 Netflix/RxJava라는 도구를 오픈소스 라이선스 하에 배포하였다.(나중에 이것은 "Reactive/RxJava로 재명명되었다.) 넷플릭스는 RxJava 위에 Groovy 기반으로 수많은 프로그래밍을 수행했었는데, 이것은 Java에도 사용될 수 있도록 열려 있으며 람다(Lambda)를 사용하면 Java 8과도 매우 잘 들어맞게 되어 있다. Reactive Stream에 대한 연결체도 있다. RxJava는 David Karnok의 Reactive 세대 분류 체계에 따르면 2세대 라이브러리에 속한다.


Reactor 

Reactor는 Pivotal의 오픈소스팀(이 팀에서 스프링을 만들었다)이 만든 Java 프레임워크이다. 이 프레임워크는 Reactive Stream 상에서 직접 빌드하는데, 그래서 브릿지가 필요치 않다. Reactor IO 프로젝트는 Netty나 Aeron과 같은 저수준 네트워크 런타임에 대한 래퍼를 제공한다. Reactor는 David Karnok의 Reactive 세대 분류 체계에 따르면 4세대 라이브러리에 속한다.

 

Spring Framework 5.0 

스프링 프레임워크 5.0(첫 마일스톤은 2016년 6월에 제작되었다)부터 리액티브 기능들이 프레임워크 내부에 포함되었는데, 여기에 HTTP 서버와 클라이언트를 만들 수 있는 도구들이 포함되어 있다. 스프링을 이용하여 웹 개발을 하는 기존 사용자들은 HTTP 요청을 처리하기 위해 컨트롤러 메소드를 어노테이션으로 장식(decorate)하는 매우 친숙한 프로그래밍 모델을 접할 수 있을 것인데, 이 방식은 대부분의 경우 리액티브 요청과 배압에 대한 걱정을 프레임워크단이 처리하도록 한다. 스프링 어플리케이션은 Reactor 상에서 만들어지는데, 동시에 이 기능을 어떤 라이브러리(예를 들어 Reactor나 RxJava)를 이용하여 표현할지를 허용하는 API를 노출한다. 사용자는 서버사이드 네트워크 스택을 위해 Tomcat, Jetty, (Reactor IO를 통한) Netty, 그리고 Undertow 중 하나를 선택할 수 있다.

 

Ratpack 

Ratpack은 HTTP 상에서 고성능 서비스를 구축하기 위해 사용되는 라이브러리 집합이다. Netty 상에서 빌드되며 상호운용성(interoperability)를 위해 Reactive Stream을 구현하고 있다.(그래서 예를들어, 상위 스택에서 다른 Reactive Stream을 사용할 수 있다.) 스프링이 네이티브 컴포넌트로서 지원되며, 그래서 몇 개의 단순한 유틸리티 클래스들을 이용하는 데에 의존성 주입 기능을 지원하도록 할 수 있다. 또, 자동 설정기능(auto-configuration)이 지원되어 SpringBoot 사용자는  Spring Boot가 직접 지원하는 내장 서버들 중 하나를 사용하는 대신, Ratpack을 스프링 어플리케이션 내부에 탑재하여 HTTP 엔드포인트를 기동할 수도 있다.


Akka 

Akka는 스칼라나 Java에서 액터 패턴을 이용하여 어플리케이션을 빌드하기 위한 툴킷인데, Akka 스트림과 Reactive Stream의 계약을 사용하는 프로세스간 통신(interprocess communication) 기능이 탑재되어 있다. Akka는 David Karnok의 Reactive 세대 분류 체계에 따르면 3세대 라이브러리에 속한다.


 

왜 지금 이슈가 되는가?

 

엔터프라이즈 자바 영역에서 리액티브 기법이 떠오르게 된 계기는 무엇일까? 그저 - 사람들이 반짝거리는 새로운 장난감이 있는 밴드웨건에 뛰어드는 것 같은  - 기술적인 유행에 불과한 것은 아니다. 시작은 효율적인 자원 사용을 위함이었고, 다른 말로 서버와 데이터 센터를 위해 적은 비용을 지불하기 위함이었다. 리액티브 프로그래밍이 약속하는 것은 개발자들이 보다 적은 작업으로 많은 일을 할 수 있도록 해 주는 것이고, 적은 수의 스레드로 더 많은 부하를 처리할 수 있도록 하는 것이다. 이로 인해 리액티브 프로그래밍과 넌블럭킹/비동기IO 간의 접점이 부각되는 것이다. 적절한 문제상황에 대해 사용하면 그 효과는 드라마틱하다. 잘못된 상황에 사용할 경우, 정반대의 결과를 얻게 될 것이다.(실제로 상황을 더 나쁘게 만들 수 있다.) 또 기억해야 할 것은, 적절한 문제상황에 적용할 때에도 거저 되는 것은 없다는 것이다. 리액티브 프로그래밍은 문제를 해결해주는 것이 아니라 해결책을 구현하기 위해 사용하는 툴박스를 제공할 뿐이다.


 

결론

 

지금까지 리액티브 프로그래밍의 움직임과 현대 엔터프라이즈 영역 내에서의 적용에 대해 폭넓고 개략적으로 다뤄보았다. JVM에서 사용할 수 있는 리액티브 라이브러리나 프레임워크들이 많이 있으며, 그 모든 것들이 활발히 개발되고 있다. 대체로 유사한 기능을 제공하고 있긴 하지만, Reactive Stream들 덕분에 점점 더 상호운용이 가능해지고 있다. 이 시리즈의 다음 글에서는 보다 실질적인 내용을 다뤄볼 것이다. 그리고 리액티브이라는 것이 어떤 의미이고 왜 중요한지에 대해 보다 명확히 이해할 수 있도록 실제 코드 샘플도 살펴볼 것이다. 또 FRP에서 F가 중요한지에 대해, 그리고 배압과 넌블럭킹 코드라는 개념이 어떻게 프로그래밍 스타일에 엄청한 영향을 끼쳤는지를 이해하는 데에 꽤 많은 시간을 할애할 것이다. 그리고 가장 중요한 점으로, 언제 그리고 어떻게 리액티브 프로그래밍을 적용할 것인지, 그리고 언제 예전 스타일과 스택을 유지할 것인지에 대해 결정하는 데에 도움을 줄 것이다.