본문 바로가기

RxSwift

[RxSwift] Observable

안녕하세요 태태입니다. 💜

이번 포스팅은 RxSwift의 Obervable에 대해 학습해보려합니다. 👀

아래 링크를 참고하여 학습하였습니다. 🙇🏻‍♂️ 
https://github.com/fimuxd/RxSwift/blob/master/Lectures/02_Observables/Ch2.%20Observables.md

 

GitHub - fimuxd/RxSwift: RxSwift를 스터디하는 공간

RxSwift를 스터디하는 공간. Contribute to fimuxd/RxSwift development by creating an account on GitHub.

github.com


Observable란? 

Rx의 핵심이라고 할 수 있습니다. 
Observer(관찰자)가 Observable을 subscribe(구독)하면서 Observable이 Emit(방출)하는 이벤트에 반응하는 구조 입니다.

* 이벤트 : 숫자나 커스텀한 인스턴스 같은 값을 가질 수 있고, 또는 Tap과 같은 제스처를 인식할 수도 있습니다.

 

이러한 개념들을 시각화해 둔 것이 있는데 바로 Marble Diagram이 있습니다.


- Marble Diagram ? 
 시간의 흐름에 따라 값을 표시, 시간은 왼쪽 > 오른쪽으로 흐름 

https://rxmarbles.com/

 

RxMarbles: Interactive diagrams of Rx Observables

 

rxmarbles.com


- Observable 생명주기


- next

이 Observable은 1, 2, 3 세 개의 각각 요소들을 방출합니다.
새로운 항목들을 방출할때 마다 onNext 메서드를 호출합니다. 

- completed 

세 개의 tap 이벤트를 방출한 뒤 완전히 종료됩니다. 
오류가 발생하지 않았다면 Observable은 마지막 onNext를 호출한 후 onCompleted 메서드를 호출합니다.

 

- error

 

이 Observable은 완전히 종료되었지만, error 이벤트를 통해 종료된 것 입니다.
기대하는 데이터가 생성되지 않았거나, 다른 이유로 오류가 발생할 경우 오류를 알리기 위해 onError 메서드를 호출합니다.
onError 메서드가 호출되면 onNext나 onCompleted는 더 이상 호출 되지 않습니다. 

 


- Observable 생성

Observable을 생성하는 방법은 여러가지가 있습니다.
create, defer, empty / never / throw, from, just, of, range 등... 
그 중 just, of, from에 대해서 알아보겠습니다.

- just

just는 from과 비슷하지만, 단순히 배열이나 iterable을 단일 항목으로 방출합니다.

let observable = Observable<String>.just("RxSwift")

위 코드의 Observable은 "RxSwift" 를 방출합니다.

 

- of 

let observable = Observable<String>.of("Rx", "Swift")

위 코드는 Array가 아닌 String타입 입니다. Array를 Observable array로 만들고 싶으면 array를 .of 연산자에 넣으면 됩니다.

let observable = Observable<[String]>.of(["Rx", "Swift"])

이렇게 하면 just 연산자를 사용한 것과 같이 ["Rx", "Swift"]를 단일요소로 가지게 됩니다.

 

- from

let observable = Observable<String>.from(["Rx", "Swift"])

from 연산자는 일반적인 array 각각 요소들을 하나씩 방출합니다. 해당 연산자는 오직 array만 취합니다.
위 코드의 Observable은 "Rx" 와 "Swift"를 각각 방출합니다.


- Observable 구독

생성을 하였으니, 시퀸스를 구독하고 실행할 수 있도록 해보겠습니다. 이 Observable을 구독해야 이벤트를 방출합니다.

 

- .subscribe()

let observable = Observable.of("Rx", "Swift")
observable.subscribe({ (event) in 
	print(event)
})

/* next("Rx")
   next("Swift")
   completed
*/

.subscribe 는 escaping(탈출) 클로저로 String 타입을 Event로 가지고 Disposable을 리턴합니다.
위 코드에서는 next, completed 이벤트까지 포함되고 있습니다. 값만 print 하기 위해서 아래와 같이 수정해주면,

observable.subscribe { event in
		if let element = event.element {
        		print(element)
        }
}
/* Rx
   Swift 
*/

값만 print 해볼 수 있습니다. 또한, 위 코드를 축약형으로도 나타낼 수 있습니다.

observable.subscribe(onNext: { (event) in
		print(event)
})
/* Rx
   Swift
*/

.onNext 클로저는 .next 이벤트만을 argument로 취한 뒤 다른 것들은 무시하게 됩니다.

 

현재까지 하나 또는 여러개의 요소를 가진 Observable에 대해서만 알아보았습니다.
그렇다면, 요소를 가지지 않는 Observable은 어떻게 해야 할까요?

- .empty()
empty 연산자는 .completed 이벤트만 방출합니다.

let observable = Observable<Void>.empty()

observable.subscribe(
	OnNext: { (element) in
		print(element)
},
	OnCompleted: {
		print("Completed")
})

/* Completed
*/

empty Observable의 용도는
즉시 종료할 수 있는 Observable을 리턴하고 싶을때
의도적으로 0개의 값을 가지는 Observable을 리턴 하고 싶을 때 사용한다고 합니다.

- .never()

let observable = Observable<Any>.never()

observable.subscribe(
	OnNext: { (element) in
		print(element)
},
	OnCompleted: {
		print("Completed")
})

이렇게 하면 Completed 조차 print 되지 않습니다.


- Disposing & Terminating

- dispose()
구독을 수동적으로 취소해 Observable을 종료
합니다.

let observable = Observable.of("Rx", "Swift")

let subscription = observable.subscribe({ event in
	print(event)
})

subscription.dispose()

String의 Observable을 생성하고 구독합니다. 여기서 취소하고 싶으면 dispose()를 호출하면 됩니다.
구독을 취소하거나 dispose 한 뒤에는 이벤트 방출이 정지됩니다.
위 Observable 안에는 2개의 요소만 있어, dispose()를 호출하지 않아도 Completed가 print 되지만
요소가 무한히 있다면 dispose()를 호출해야 Completed가 print 됩니다.

매번 이렇게 수동적으로 관리하긴 힘들고 효율적이지 못합니다.

 

RxSwift에서는 이를 해결하기 위해 DisposeBag 타입을 제공합니다.
DisposeBag은 할당 해제 하려고 할 때마다 dispose()를 호출합니다.

let disposeBag = DisposeBag()

Observable.of("Rx", "Swift")
	.subscribe({ event in
	 print(event)
})
.disposed(by: dispiseBag)

subscribe를 통해서 방출되는 값들을 disposeBag에 담아 한번에 처리해줍니다.
disposebag을 subscription에 추가하거나 수동적으로 dispose를 호출하지 않는다면, 메모리 누수가 일어날 것입니다.
걱정마세요, Swift 컴파일러가 경고로 알려줄겁니다.👍

이외에도, create()를 통해 Disposable.create()를 리턴해주는 방법도 있습니다.



이번 포스팅에서는 RxSwift에서 가장 중요하지만 또 가장 기본이 되는 ObserVable에 대해서 알아봤습니다 😊
긴 글 읽어주셔서 감사합니다 🙇🏻‍♂️


참고 자료)

https://github.com/fimuxd/RxSwift/blob/master/Lectures/02_Observables/Ch2.%20Observables.md

 

GitHub - fimuxd/RxSwift: RxSwift를 스터디하는 공간

RxSwift를 스터디하는 공간. Contribute to fimuxd/RxSwift development by creating an account on GitHub.

github.com


https://reactivex.io/documentation/ko/observable.html

 

ReactiveX - Observable

Observable ReactiveX에서 옵저버는 Observable을 구독한다. Obseravable이 배출하는 하나 또는 연속된 항목에 옵저버는 반응한다. 이러한 패턴은 동시성 연산을 가능하게 한다. 그 이유는 Observable이 객체를

reactivex.io

https://green1229.tistory.com/187?category=936879 

 

RxSwift - Observable

안녕하세요. 그린입니다🟢 이번 포스팅에서는 RxSwift의 Observable에 대해 학습해보겠습니다🧑🏻‍💻 그동안 RxSwift를 공부하면서 너무 중구난방으로 블로깅도하고 학습한 경향이 있는것같아요.

green1229.tistory.com

RxSwift 학습에 대해서 조언을 주신 Green🟢 에게 감사의 말씀을 전합니다💚

'RxSwift' 카테고리의 다른 글

[RxSwift] Subject 예시 코드와 결과  (0) 2023.12.02
[RxSwift] RxSwift ?  (0) 2022.02.20