[RxJava] RxJava 이해하기 - 1. Reactive Programming 이란



Reactive Programing

RxJava를 시작하기 앞서, Reactive Programming이 무엇인지에 대해 알아보려 한다.

Reactive Programming이란 데이터 흐름과 전달에 관한 프로그래밍 패러다임이다.

우리는 주로 알고리즘 문제와 같이 절차를 명시하여 순서대로 실행되는 Imperative Programming(명령형 프로그래밍)을 한다. 반면 Reactive Programming이란 데이터의 흐름을 먼저 정의하고 데이터가 변경되었을 때 연관된 작업이 실행된다. 즉 프로그래머가 어떠한 기능을 직접 정해서 실행하는 것이 아닌, 시스템에 이벤트가 발생했을 때 알아서 처리되는 것이다.

기존의 프로그래밍 방식을 Pull 방식, Reactive 프로그래밍 방식을 Push 방식이라고도 한다.
Pull 방식은 데이터를 사용하는 곳(Consumer)에서 데이터를 직접 가져와서 사용한다면,
Push 방식은 데이터의 변화가 발생한 곳에서 새로운 데이터를 Consumer에게 전달한다.

따라서 Reactive 프로그래밍은 주변 환경과 끊임없이 상호작용을 한다. 다만 프로그램이 주도하는 것이 아니라 환경이 변하면 이벤트를 받아 동작함으로써 상호작용한다.


RxJava

RxJava는 ReactiveX의 Java 언어 라이브러리로, 2013년 2월 넷플릭스에서 처음 소개하였다. 2016년 10월 RxJava2를 발표하였으며 가장 최근인 2020년 2월 RxJava3를 배포했다.

공식사이트의 ReactiveX 설명은 다음과 같다.

:pushpin: ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.

It extends the observer pattern to support sequences of data and/or events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O.

번역하면,

  • ReactiveX는 관찰가능한 절차를 통해 비동기, 이벤트 기반 프로그램을 구성하기 위한 라이브러리이다.
  • Observer Pattern을 확장하며, Sequence를 조합할 수 있는 연산자를 지원한다.
  • low-level Thread, 동기화, Thread 안전성, non-blocking I/O에 관한 우려를 줄인다.


RxJava는 러닝 커브가 가파르다. 전통적인 스레드 기반의 프로그래밍을 사용하는 자바와 접근 방식이 다르기 때문이다. 여러 스레드를 사용하는 경우 예상치 못한 문제가 발생할 수도 있고 디버깅하기도 어렵다.

따라서 RxJava는 함수형 프로그래밍 방식을 도입하였다. 함수형 프로그래밍은 Side Effect가 없는 순수 함수를 지향하기 때문에 Thread-Safe하다.

ReactiveX의 이러한 방식을 구성하게 해주는 핵심 요소가 바로 ObservableOperator(연산자)인데, 다음 포스트에서 자세히 다룰 예정이다.(아마도..:astonished:)


RxJava 예제

import io.reactivex.rxjava3.core.Observable;

public class RxExample {
    public static void main(String[] args){
        Observable.just(1, 2, 3)
                .map(x -> x*10)
                .subscribe(System.out::println);
  }
}
  • Observable : ReactiveX의 핵심 요소이자 데이터 흐름에 맞게 Consumer에게 알림을 보내는 Class이다.
  • just() : 가장 간단한 Observable 생성 방식이다. (생성 연산자라고도 한다)
  • map() : RxJava의 연산자이다. 데이터를 원하는 형태로 바꿀 수 있다.
  • subscribe() : Observable은 구독(subscribe)을 해야 데이터가 발행된다. 따라서 Observable을 구독하여 데이터를 발행 후, 수신한 데이터를 원하는 방식으로 사용(System.out::println)한다.


Marble Diagram

Marble Diagram은 RxJava를 이해하는 핵심 도구이다. 데이터의 흐름과 연산자를 이해하는 데 큰 도움이 된다.

예제에서 실행한 코드를 Marble Diagram으로 바꾸면 다음과 같다. img

:bulb: 1, 2, 3이 연산자 map을 거쳐 10, 20, 30이 되었다


각 컴포넌트의 자세한 설명은 공식사이트에서 가져왔다.

img

  • 가로 실선 : Timeline
  • 모형(★, ●, ■, ◆, …) : Observable에서 발행하는 데이터
  • 세로 실선(파이프) : 데이터 발행의 완료를 의미함, 발행 완료 이후에는 더 이상 데이터 발행이 불가능하다
  • 가운데 박스 : 연산자, 이 박스를 거치면 데이터가 변한다
  • X : 오류가 발생했음을 의미한다

:bulb: 예제를 해석하면, ★, ▼, .., ◆ 데이터가 차례로 들어와 ◆ 이후 데이터 발행이 완료되었다.
각 데이터는 flip 연산자를 거쳐 새롭게 변환되었으며(▼ -> ▲),
초록색 오각형 이후 어떠한 오류로 인해 데이터 발행이 비정상적으로 종료되었다.

마지막으로, Marble Diagram을 쉽게 이것 저것 실행해볼 수 있는 웹사이트를 소개하고자 한다. 모형을 이리저리 옮길 수 있으며 여러 연산자의 역할과 데이터의 흐름을 이해하기 아주 좋다. 나도 아직 다 해보진 못했지만, RxJava를 공부하면서 모든 연산자를 한번 씩은 실행해보며 짚고 넘어갈 것이다!



:bookmark: REFERENCE
유동환, 박정준, 「RxJava 프로그래밍」, 한빛미디어
ReactiveX