RxJava 스터디에서 사용될 교재 ‘RxJava 프로그래밍’을 공부하며 정리할 내용을 포스팅할 예정이다.
Chapter 1
리액티브 프로그래밍
명령형 프로그래밍과 리액티브 프로그래밍의 차이
기존의 명령형 프로그래밍은 작성된 코드가 정해진 절차에 따라 순서대로 실행. 그러나 리액티브 프로그래밍은 데이터 흐름을 먼저 정의하고 데이터가 변경되었을 때 연관되는 함수나 수식이 업데이트되는 방식
기존 방식은 데이터를 가져오는(Pull) 방식이라면, 리액티브 프로그래밍은 데이터의 변화가 발생했을 때 변경이 발생한 곳에서 새로운 데이터를 보내는(Push) 방식.
리액티브 프로그래밍을 해야하는 이유
기존 방식(콜백이나 옵서버 패턴)은 옵서버가 1개이거나 단일 스레드 환경에서는 문제가 없지만 멀티 스레드 환경에서는 데드락과 동기화 문제가 생길 수 있다. 따라서 리액티브 프로그래밍을 구현하려면 함수형 프로그래밍의 도움이 필요하다. 함수형 프로그래밍은 부수효과가 없는 순수 함수를 지향하기 때문에 멀티스레드 환경에서도 안전하다.
리액티브 프로그래밍을 JVM 위에 자바 언어로 구현해 놓은 라이브러리가 RxJava이다.
Chapter — 2
Observable 클래스
Observable이란?
옵서버 패턴이 구현되어 있는 클래스. 옵서버 패턴은 객체의 상태 변화를 관찰하는 관찰자(옵서버) 목록을 객체에 등록한 후, 상태 변화가 있을 때마다 메스드를 호출하여 객체가 직접 목록의 각 옵서버에게 변화를 알려줌
라이프 사이클은 존재하지 않고, 보통 단일 함수를 통해 변화만 알림
Observable의 3가지 알림
- onNext — Observable이 데이터의 발행을 알림
- onComplete — 모든 데이터의 발행을 완료했음을 알림. onComplete 이벤트는 단 한번만 발생하며, 발생한 뒤에는 onNext 이벤트가 발생해서는 안됨
- onError — Observable에서 에러가 발생했음을 알림. 이 이벤트가 발생하면 이후에 onNext 및 onComplete이벤트가 발생하지 않음. Observable 실행을 종료
데이터 발행자와 수신자
-데이터 발행자
- Observable
- Single
- Maybe
- Subject
- Completable
-데이터 수신자
- 구독자(Subscriber)
- 옵서버(Observer)
- 소비자(Consumer)
뜨거운 Observable과 차가운 Observable
-뜨거운 Observable
- Observable을 팩토리 함수로 만든 뒤, subscribe() 함수를 호출하여 구독하지 않으면 데이터를 발행하지 않음.
- 구독자가 구독한 시점부터 Observable에서 발행한 값을 받음
- 구독자가 존재 여부와 관계없이 데이터를 발행하는 Observable. 따라서 여러 구독자를 고려할 수 있음
- 구독자는 Observable에서 발행하는 데이터를 처음부터 모두 수신할 것으로 보장할 수 없음
- 배압(Back Pressure)을 고려해야 한다. 배압은 Observable에서 데이터를 발행하는 속도와 구독자가 처리하는 속도 차이가 클 때 발생. Flowable이라는 특화 클래스를 사용해야함
- 예로는 마우스 이벤트, 키보드 이벤트, 시스템 이벤트, 센서 데이터
-차가운 Observable
- 구독자가 구독하면 준비된 데이터를 처음부터 발행
- 예로는 웹 요청, 데이터베이스 쿼리, 파일 읽기
차가운 Observable을 뜨거운 Observable 객체로 변환하는 방법은
- Subject 객체를 만듬
- ConnectableObservable 클래스를 활용
Subscribe이란?
Observable을 만들었더라도, subscribe 함수를 호출해야 실제 데이터가 발행됨.
오버로딩 된 subscribe 함수의 의미
- 인자 0개 — onNext와 onComplete 이벤트를 무시. onError 이벤트 발생했을 시 OnErrorNotImplementedException을 throw.
- 인자 1개 — onNext이벤트 처리. onError시 위와 같은 익셉션 throw
- 인자 2개 — onNext, onError 이벤트 처리
- 인자 3개 — onNext, onError, onComplete 이벤트 처리
모든 subscribe 함수는 Disposable 인터페이스의 객체를 리턴. Disposable은 dispose()와 isDisposed()의 두개 함수를 가지고 있음.
Disposable 인터페이스 함수
- dispose() — Observable에게 더 이상 데이터를 발행하지 않도록 구독을 해지하는 함수. Observable이 onComplete 알림을 보냈을 때 자동으로 dispose()를 호출해 Observable과 구독자의 관계를 끊음
- isDispose() — Observable이 데이터를 발행하지 않는지(구독을 해지했는지) 확인하는 함수(리턴타입 Boolean)
Observable를 생성하는 팩토리 함수들
- just()
- 인자로 넣은 데이터를 차례로 발행
- 인자로는 최대 10개 넣을 수 있음(타입이 같아야함)
- create()
- just함수와 다르게 onNext, onComplete, onError같은 알림을 개발자가 직접 호출해야함.
- RxJava에 익숙한 사용자만 활용하도록 권고(RxJava javadoc에 따르면)
- 2의 이유는 Observable이 구독 해지 되었을 때 등록된 콜백을 모두 해제해야함(메모리 누수 문제), 구독자가 구독하는 동안에만 onNext와 onComplete이벤트를 호출해야하고, 에러가 발생했을 때는 오직 onError이벤트로만 에러를 전달해야하고, 배압(back pressure)을 직접 처리해야함
-fromArray()
- 배열에 들어 있는 데이터 처리시 사용
-fromIterable()
- Iterable 인터페이스를 구현한 클래스의 데이터 처리시 사용(List, Set, Queue 인터페이스 계열)
-fromCallable()
- 자바 5에서 추가된 비동기 프로그래밍에 사용되는 Callable 인터페이스 처리시 사용
- Callable 인터페이스는 call() 메서드 하나만 가지고 있고, call()메서드는 인자가 없고, 실행결과를 리턴하고, 다른 스레드에서 실행됨
-fromFuture()
- 자바 5에서 추가된 비동기 프로그래밍에 사용되는 Future 인터페이스 처리시 사용
- Executor 인터페이스를 구현한 클래스에 Callable 객체를 인자로 넣어 Future 객체를 반환
-fromPublisher()
- 자바 9의 표준인 Flow API 일부인 Publisher를 처리시 사용
- create()와 마찬가지로 onNext()와 onComplete() 함수를 호출할 수 있음
Single 클래스
Observable 클래스는 데이터를 무한하게 발행할 수 있지만 Single 클래스는 오직 1개의 데이터만 발행하도록 한정.
데이터 하나가 발행과 동시에 종료(onSuccess)됨
onNext()와 onComplete() 함수가 onSuccess() 함수로 통합된 것이기 때문에 Single클래스는 onSuccess()와 onError()함수로 구성
-just()
- Observable 함수와 같이 사용
Observable에서 Single 클래스 사용하는 방법
- Single.fromObservable(source)
- Observable.just(“값”).single(“default 값”) — just에 값이 2개가 들어가는 경우 두번째 값을 발행하면서 onNext 이벤트가 발생했을 때 에러
- Observable.fromArray(“배열”).first(“default 값”)
- Observable.empty().single(“default value”)
- Observable.just(“값”,”값”).take(1).single(“default 값”)
Maybe 클래스
Single 클래스와 마찬가지로 최대 데이터 하나를 가질 수 있지만 데이터 발행 없이 바로 데이터 발생을 완료할 수도 있다. (Single클래스는 1개 완료, Maybe 클래스는 0 혹은 1개 완료) 즉, Maybe 클래스는 Single 클래스에 onComplete 이벤트가 추가된 형태
Subject 클래스
차가운 Observable을 뜨거운 Observable로 바꿔줌. 이 클래스의 특성은 Observable의 속성과 구독자의 속성이 모두 있다는 점. Observable처럼 데이터를 발행할 수도 있고, 구독자처럼 발행된 데이터를 바로 처리할 수 있다.
RxJava에서 제공하는 주요 Subject클래스에는 AsyncSubject, BehaviorSubject, PublishSubject, ReplaySubject 등이 있다.
AsyncSubject 클래스
create() 팩토리 함수로 생성
Observable에서 발행한 마지막 데이터를 얻어올 수 있는 클래스. 구독 후 onComplete() 함수가 호출되어야 마지막 값을 발행.
onComplete() 함수가 호출된 뒤, onNext()가 호출되어도 해당 이벤트를 무시. 이후에 구독하면 onComplete() 이번의 값으로 발행.
BehaviorSubject 클래스
구독을 하면 가장 최근 값 혹은 기본값을 넘겨주는 클래스. createDefault(“기본값”) 팩토리 함수로 생성. subscribe()함수를 호출했을 때 그전까지 발행한 값이 없다면 기본값을 대신 발행해야하기 때문.
PublishSubject 클래스
구독자가 subscribe() 함수를 호출하면 값을 발행하기 시작. 해당 시간에 발행한 데이터를 그대로 구독자에게 전달 받음. create() 팩토리 함수를 호출해 생성
ReplaySubject 클래스
차가운 Observable처럼 동작. 구독자가 새로 생기면 항상 데이터의 처음부터 끝까지 발행. 모든 데이터 내용을 저장해두는 과정 중 메모리 누수가 발생할 가능성을 염두에 두고 사용할 때 주의해야함.
ConnectableObservable 클래스
- Subject 클래스처럼 차가운 Observable을 뜨거운 Observable로 변환
- Observable을 여러 구독자에게 공유할 수 있으므로, 원 데이터 하나를 여러 구독자에게 동시에 전달할 때 사용.
- subscribe() 함수를 호출해도 아무 동작이 일어나지 않는다. 새로 추가된 connect() 함수가 호출한 시점부터 subscribe()함수를 호출한 구독자에게 데이터를 발행하기 때문.
- publish()함수를 호출하여 객체를 생성
