이 포스팅의 stream을 통한 예시는 The introduction to Reactive Programming you've been missing의 부분을 번역하여 작성했습니다.
Reactive programming is programming with asynchronous data streams.
Reactive programming은 비동기식 데이터 스트림으로 프로그래밍하는 것
예를 들어 검색버튼을 클릭하고 검색어를 통해 API에 요청하는것은 흔히 이용하는 비동기식 이벤트입니다. callback을 활용해 비동기 이벤트들을 처리할 수도 있지만 search stream이라는 하나의 비동기 데이터 스트림으로 처리할 수 있습니다.
이처럼 Reactive programming은 데이터스트림에서 일어나는 변화를 지속적으로 관찰(Observer)하고 이에 따른 동작을 수행해야 합니다.
스트림이 Reactive의 핵심이라면 친숙한 "버튼 클릭" 이벤트를 보며 살펴보겠습니다.
버튼을 클릭하게 되면 value, error, completes 신호 세 가지를 방출할 수 있습니다. 예를 들어 해당 버튼을 포함하는 현재 창이나 보기가 닫힐 때 "완료됨"이 발생한다고 볼 수 있습니다.
값이 방출될 때 실행할 함수, 오류가 방출될 때 다른 함수, '완료'가 방출될 때 다른 함수를 정의하여 방출된 이벤트를 비동기식으로 만 캡처합니다 . 때로는 이 error, completion을 생략할 수 있으며 값에 대한 함수 정의에만 집중할 수 있습니다.
스트림을 "listening" 하는 것을 subscribing 이라고 합니다. 우리가 정의하는 기능은 observers입니다. 스트림은 subject(또는 "observable")입니다. 이것이 바로 옵저버 디자인 패턴 입니다.
해당 다이어그램을 그리는 다른 방법은 ASCII를 사용하는 것입니다.
--a---b-c---d---X---|->
a, b, c, d are emitted values
X is an error
| is the 'completed' signal
---> is the timeline
이것보다 좀 더 새롭게 원래 클릭 이벤트 스트림에서 변형된 새 클릭 이벤트 스트림을 생성할 것입니다. 먼저 버튼이 클릭된 횟수를 나타내는 카운터 스트림을 만들어 보겠습니다.
일반적인 반응형 라이브러리에서 각 스트림에는 map
, filter
, scen
등 많은 기능이 연결되어 있습니다. clickStream.map(f)
과 같은 기능 중 하나를 호출하면 클릭 스트림을 기반으로 새 스트림을 return합니다. 여기서 중요한건 원래 클릭 스트림은 수정하지 않습니다. 이것은 불변성(immutability)이라는 특성입니다. 이런 부분은 Reactive streams과 잘 어울립니다. 이러한 특성때문에 clickStream.map(f).scan(g)
과 같은 기능을 chain할 수 있습니다.
clickStream: ---c----c--c----c------c-->
vvvvv map(c becomes 1) vvvv
---1----1--1----1------1-->
vvvvvvvvv scan(+) vvvvvvvvv
counterStream: ---1----2--3----4------5-->
이 map(f)
함수는 f
사용자가 제공 하는 함수에 따라 방출된 각 값을(새 스트림으로) 대체 합니다.
Reactive의 실제 성능을 보여 주기 위해 "더블 클릭" 이벤트 스트림을 사용한다고 가정해 보겠습니다. 예를 들어, 새로운 스트림이 세 번 클릭을 두 번 클릭으로, 또는 일반적으로 여러 번 클릭(2번 이상)으로 고려하기를 원한다고 가정해 보겠습니다. 심호흡을 하고 전통적인 명령적이고 위풍당당한 방식으로 그것을 어떻게 하는지 상상해 보세요. 상당히 지저분하게 들리겠지만, 상태를 유지하기 위한 변수와 시간 간격을 만지작거리는 변수도 있을 것입니다.
반응성에서는 꽤 간단합니다. 단지 4줄의 코드만 있으면 됩니다. diagrams으로 생각하는 것은 초보자든 전문가든 스트림을 이해하고 구축하는 가장 좋은 방법입니다.
회색 상자는 한 스트림을 다른 스트림으로 변환하는 기능입니다. 먼저 250밀리초의 "이벤트 무음"이 발생할 때마다 목록에 클릭수를 누적합니다 buffer(stream.throttle(250ms))
. 결과는 목록의 스트림이며 map()
각 목록을 해당 목록의 길이와 일치하는 정수로 매핑 하는 데 적용 합니다. 마지막으로 함수를 1
사용하여 정수를 무시 filter(x >= 2)
합니다.
이 예는 빙산의 일각에 불과합니다. 예를 들어 API 응답 스트림에 동일한 작업을 적용할 수 있습니다.
참고로 reactivex.io에는 이렇게 한 줄로 설명되어있습니다.
An API for asynchronous programming with observable streams
observable 스트림을 사용하는 비동기 프로그래밍을 위한 API
즉, reactive programming은 프로그래밍 패러다임, reactive extensions는 API입니다.
The introduction to Reactive Programming you've been missing