[RxSwift] RxSwift란 - Observable, Disposable

2021. 2. 11. 02:36RxSwift

반응형

RxSwift에 대해서는 공부를 혼자 진행하고 있었는데, 이제부터 RxSwift도 혼자 공부하던 것들을 정리해서 포스팅해보려고 합니다..

 

우선 RxSwift에 대한 처음 포스팅이기 때문에 오늘은 RxSwift가 무엇인지 그리고 가장 기본적인 것들을 정리해보겠습니다.

 

RxSwift라고 하면 무엇이 생각나시나요...?

취직을 위한 우대사항 조건..(?), MVVM이랑 같이 쓰는 것..(?), 비동기..(?)

 

뭐 위에서 말한 사항들이 전부 조합되어 있긴한 것 같습니다.

 

그렇다면 오늘은 RxSwift에 대해 가볍게 알아보고 정리해보겠습니다.

 

RxSwift란

우선 RxSwift는 기본으로 지원해주는 프레임워크는 아니고 외부의 라이브러리를 가져다써야하는 프레임워크입니다. 즉, ReactiveX라는 곳에서 만든 라이브러리로 사용하기 위해서는 Cocoapods를 통해 프로젝트로 가져와야 합니다.

 

RxSwift는 Reactive eXtension + Swift의 합성어로 이루어진 용어입니다. 그렇다면 어떤 뜻을 지닌 언어일까요? 

 

비동기 프로그래밍을 관찰 가능한 흐름으로 지원해주는 API입니다.

옵저버 패턴과 이터레이터 패턴 그리고 함수형 프로그래밍을 조합한 반응형 프로그램입니다.

 

여러 용어들이 많이 나왔는데 관찰 가능한, 반응형이라는 단어들이 눈에 띕니다.

각 단어에 대해 어떤 의미인지 하나씩 살펴보겠습니다.

 

반응형

반응을 한다고 뜻대로 이해할 수 있을 것 같습니다. 예를 들어, UIButton을 눌렀을 때에 반응을 해야하고 서버에서 데이터를 받아왔을 때 어떤 반응을 해야한다고 하면 그 때 각각으로 원하는 동작들을 수행한다는 뜻입니다. 즉, 반응성이 있다는 것이죠. (사실 너무 당연한 말이죠..? 직접해봐야 와닿는 것 같습니다.)

 

관찰 가능한

이전에 말했던 반응형과 조합하여 사용하는 것입니다. 바로 어떤 이벤트를 관찰하다 이벤트가 방출되었을 때, 그 이벤트를 위해 반응을 해주는 것입니다. 즉, 버튼을 누르는지, 서버로부터 데이터를 성공적으로 받아왔는지를 관찰하는 것입니다.

 

이러한 용어들을 조합하여 비동기 프로그래밍을 쉽게할 수 있도록 도와주는 것이 RxSwift입니다.

 

그렇다면 이 RxSwift를 왜 사용할까요? 제가 사용하면서 생각이 든 몇가지 이유를 나열해보겠습니다.

  1. RxSwift을 사용하지 않은 경우는 여러 쓰레드를 넘나 들고 클로저를 넘겨서 이벤트를 처리하기 때문에, 가독성도 좋지 않고 한 번에 코드를 이해하기 힘들지만 이런 현상을 해결할 수 있다.
  2. 코드가 깔끔해진다.
  3. 비동기 처리를 모두 Observable 타입을 이용해 할 수 있다.

사용하는 이유는 더 있을 수 있으나 제가 생각했을 때는 다음과 같은 이유들이 가장 크리티컬하고 컸던 것 같습니다.

 

RxSwift는 비동기 프로그래밍을 위해 만들어진 API라고 이해하면 좋을 것 같습니다. 

다음으로는 RxSwift에서 많이 사용하게 되고 필수적인 Observable, Disposable 타입에 대해 알아보겠습니다.

 

 

Observable

Observable 타입을 이용해서 관찰 가능한 흐름이 생성되게 됩니다. 즉, 이 타입을 이용해서 관찰을 하고 들어온 값들을 처리하게 됩니다. Observer가 Observable을 구독하는 형태입니다.

 

쉽게 말해서 Observable을 구독해서 알맞는 이벤트를 처리한다고 이해하면 좋을 것 같습니다.

 

여기서 Observable은 3가지의 이벤트에 반응을 합니다.

  • next : 어떤 항목을 배출하는데 이것이 바로 next이다. 즉, 이 이벤트를 받아서 원하는 형태로 처리한다.
  • error : 값을 배출하다 에러가 발생한 경우 error 이벤트를 방출하고 스트림을 종료시킨다.
  • complete : 성공적으로 next 이벤트가 완료되었을 때, complete 이벤트가 발생한다. 이 경우에도 스트림이 종료된다.

error, complete가 발생한 상황에는 모두 Dispose가 호출되고 스트림이 종료됩니다. 나중에 더욱 깊게가면 알겠지만 error 이벤트를 핸들링할 때, UI 관련 요소에 대한 처리는 신중하게 해주어야 합니다. (스트림이 종료되기 때문에)

 

그렇다면 간단한 예제로 Observable을 어떻게 구독해서 사용하는지 알아보겠습니다.

func fromArray(_ arr: [Int]) -> Observable<Int> {
    return Observable<Int>.create { observer -> Disposable in
        for element in arr {
            observer.onNext(element)
        }
        
        observer.onCompleted()
        
        return Disposables.create()
    }
}

fromArray([1, 2, 5, 3, 4])
    .subscribe {
        event in
        switch event {
        case .next(let value): print(value)
        case .error(let error): print(error)
        case .completed: print("completed")
        }
    }
    .dispose()
// 1
// 2
// 5
// 3
// 4
// completed

이렇듯 Observable은 next 이벤트를 통해 Element를 받아서 적절하게 처리하고 원하는 동작을 지정합니다. 그리고 스트림이 완료되면 complete가 불리고 dispose가 호출되게 됩니다.

 

Disposable 

Disposable 변수는 위에서 예시를 보면 알 수 있듯이 어떤 작업의 마지막에 불리게 됩니다. 그리고 이후에 작업이 완료됩니다. 즉, 해당 작업을 사용 후 처리할 수 있는 처분할 수 있는(?) 정도로 이해하면 좋을 것 같습니다. 그리고 Observable 타입들은 모두 Disposable 타입을 반환하는데, 이 값을 이용해서 스트림을 종료시키고 작업을 종료하는 것이 가능해집니다.

 

보통 DisposeBag이라는 레퍼런스 타입을 많이 사용하게 될텐데 Disposable 변수들을 담아두었다. 한번에 종료하고 작업을 종료할 때, 사용하기 위해 한 곳에 넣었다 처리한다고 이해하면 될 것 같습니다. 정말 쓰레기통(?) 같은 역할을 하는 것이죠.

let disposable = Observable.from([1, 2, 3, 5, 6])
    .subscribe(onNext: { element in
        print(element)
        sleep(1)
    }, onCompleted: {
        print("completed")
    }, onDisposed: {
        print("disposed")
    })
    
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    disposable.dispose()
}

// 1
// 2
// disposed


var disposeBag = DisposeBag()

button.rx.tap
    .subscribe(onNext: {
        print("Tap")
    }, onCompleted: {
        print("completed")
    }, onDisposed: {
        print("disposed")
    })
    .disposed(by: disposeBag)

위와 아래의 차이는 무엇일까요...? 우선 UI요소를 처리한 것과 그렇지 않다는 차이가 있는데, DisposeBag에 담은 경우는 바로 Dispose로 스트림을 종료시키는 것이 아니고 나중에 필요에 의해 DisposeBag을 초기화 할 수 있습니다.

 

즉, UI의 경우 스트림이 종료되지 않고 계속해서 UIButton의 이벤트를 관찰하여야하기 때문에 DisposeBag에 담아놓는 것입니다. 그리고 나중에 UIViewController가 메모리로부터 해제될 때, 스트림을 종료시켜주게 됩니다.

반응형

'RxSwift' 카테고리의 다른 글

[RxSwift] Operator란?  (0) 2021.06.21
[RxSwift] Hot & Cold Observable  (0) 2021.05.05