본문 바로가기

iOS

[iOS] RxSwift 시작하기

RxSwift 시작하기

 

앞서 RxSwift에 대하여 간단히 알아보고 개념을 익혔다.

이제 본격적으로 RxSwift를 공부하며 사용해보도록 한다.

 

비동기 프로그래밍(Asynchronous Programming)


일반적인 Class에서는 비동기 작업을 수행하고 이에 따른 모든 UI 구성을 기본적으로 비동기로 처리하기 때문에 코드가 어떠한 흐름으로 진행될 지 예측하는 것이 어렵다.

뿐 만 아니라, 코드는 사용자의 입력 혹은 네트워킹 환경 등 다양한 외부 요인에 의하여 다르게 실행된다.

Apple은 이러한 비동기에 대응하기 위해 아래와 같은 다양한 기능들을 제공하고 있다.

  • NotificationCenter : 특정 이벤트가 발생할 경우에 진행할 코드를 작성해놓고 해당 이벤트가 발생하면 코드를 진행시키는 방법.
  • Delegate Pattern : 타 클래스 혹은 API에 의해 실행될 메소드를 정의한다. 우리가 자주 보던 Delegate 메소드들이 해당 기능을 한다. 하지만 이 코드가 정확히 언제 실행될 지를 가늠하기는 어렵다.
  • Grand Central Dispatch(GCD) : 비동기 프로그래밍 실행을 추상화하는데 기여한다. Serial Queue 에 순차적으로 진행하기 위한 task들을 예약하거나 Concurrency Queue 를 통해 동시에 실행하는 것 처럼 보여지도록 실행할 수 있다.
  • Closure : 클래스 간 코드를 전달하는데 도움을 준다.

 

RxSwift 구성요소


1. Observable

  • 데이터 스냅샷을 전달할 수 있는 일련의 이벤트 시퀀스를 비동기적으로 생성한다.
  • Observable을 통해 값을 배출하고, RxSwift는 이를 관찰하며 반응한다.
  • 하나 이상의 Observer가 실시간으로 이벤트에 반응하여 들어오는 데이터를 처리하고 활용할 수 있게 한다.

 

ObservableType Protocol


`Observable` 은 3가지 타입의 이벤트만 방출할 수 있다.

  • next: 최신 값을 전송하는 이벤트
  • error: Observable이 값을 배출하다가 error 가 발생할 경우, error를 배출하고 시퀀스를 종료하는 이벤트
  • complete: 모든 이벤트가 성공적으로 방출되었을 경우 이벤트 시퀀스를 종료하는 이벤트

 

2. Operator

  • ObservableType 과 Observable 클래스에는 다양한 기능을 더욱 간편하게 제공하기 위해 많은 메소드를 제공하며 이를 Operator라고 부른다.
  • Operator는 비동기 입력을 받아 출력을 생성하기 때문에 결합 또한 간편하다.

이 부분은 이전 문서에서 자세히 다루었으니 따로 다루지는 않는다.

 

3. Scheduler

  • Rx에서의 Scheduler는 기존의 DispatchQueue와 비슷하지만 더욱 사용하기 간편하고 강력하다.
  • RxSwift 내에는 이미 Schedular가 정의되어 있기 때문에, 개발자가 따로 Schedular를 생성할 일은 드물다.
  • 기존에는 GCD를 이용하여 코드를 작성했다면, RxSwift에서는 Scheduler를 사용하여 멀티스레딩 구현을 아래와 같이 간편하게 구현할 수 있다.
ObservableSequence1
    .observeOn(backgroundScheduler)
    .map{ _ in
        print("백그라운드 스케줄러에서 실행")
    }
    .observeOn(MainScheduler.instance)
    .map { _ in
        print("메인 스케줄러에서 실행")
    }

 

이제는 Observable, Subject, Relay에 대하여 살펴보자.

Observable


Observable은 이벤트 시퀀스를 비동기적으로 생성하는 기능을 하며 지속적으로 이벤트를 발생시키는 행위를 emit 이라고 한다.

 

Observable 생성

let observable = Observable<Int>.just(1)
  • just: 오직 하나의 요소를 포함하는 Observable Sequence 생성
let observable = Observable<Int>.of(1, 2, 3, 4, 5)
  • of: 주어진 복수개의 요소를 포함하는 Observable Sequence 생성
let observable = Observable<Int>.from([1, 2, 3])
  • from: array의 요소들을 통해 Observable Sequence 생성

 

Subscribe

위에서 Observable 을 생성하는 방법에 대해 간략히 살펴보았다.

Observable Sequence를 생성하고 이를 구독하면 이벤트 방출이 진행된다.

let observable = Observable.of(1, 2, 3)
    observable.subscribe( { event in
        print(event)
    })

// next(1)
// next(2)
// next(3)
// completed

    observable.subscribe(onNext: { num in
        print(num)
    }, onCompleted: {
        print("completed")
    })

위 코드에서 .subscribeescaping closure를 통해 Event<Int> 를 갖으며 Disposable을 반환한다.

또한. .subscribe.next, .error, .completed 각각의 이벤트에 대하여 핸들링을 진행할 수 있도록 연산자를 제공한다.

 

Dispose

subscribeObservable이 이벤트를 방출할 수 있도록 트리거 해준다면 dispose는 구독을 취소하여 Observable을 수동적으로 종료시키는 기능을 한다.

let observable = Observable.of(1, 2, 3)

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

subscription.dispose()

이런식으로 수동적으로 구독을 취소할 수 있다.

하지만 각각의 구독을 일일히 관리하는 것은 효율적이지 못하고 매우 귀찮은 일이다. RxSwift는 이에 대응하여 DisposeBag 을 제공한다.

let disposebag = DisposeBag()

Observable.of(1, 2, 3)
    .subscribe {
        print($0)
    }
    .disposed(by: disposebag)

위와 같이 subscribe 이후에 disposed(by:) 메소드를 통해 이벤트 방출이 끝나면 자동으로 disposeBag에 담을 수 있다.

 

Subject


Observable은 이벤트 시퀀스를 비동기적으로 생성한다.

ObserverObservable을 subscribe하여 emit 되는 이벤트들을 핸들링한다.

Observer가 하는 일은 Observable이 하지 못하고, Observable이 하는 일은 Observer가 할 수 없게 되어있다.

이러한 제약에 대응하기 위해 RxSwift는 Subject 를 제공한다.

Subject 실시간으로 Observable에 값을 추가하고 Subscriber(Observer)에게 이벤트 방출이 가능해진다.

Subject에 대한 예제는 이전 문서에 다루었으니 여기서 다루지 않는다.

 

Relay


  • Subject와는 다르게 complete, error 를 통해 완전 종료될 수 없다.
  • subscribe를 진행하고자 할 때는, asObservable() 을 이용한다.

 

PublishRelay

  • PublishSubject를 wrapping 하여 가지고 있다.
  • Subject는 .completed, .error 이벤트를 핸들링하면 subscribe이 종료된다. 하지만 RelayDispose 이전까지 계속하여 작동하기 때문에 UIEvent와 같이 끝없이 관리해야 하는 경우에 사용하기 적절하다.

BehaviorRelay

  • BehaviorSubject를 wrapping 하여 가지고 있다.
  • 기존의 Variable 이 deprecated 되어지면서 BehaviorRelay 가 그 역할을 대신하고 있다. ( .value 를 이용하여 현재의 값을 꺼내올 수 있다.)

'iOS' 카테고리의 다른 글

[iOS] RxSwift를 이용한 Login 기능 구현  (1) 2020.10.07
[iOS] [Swift] Convenince init  (0) 2020.10.07
[iOS] KingFisher 소개  (1) 2020.09.22
[iOS] [Swift] RxSwift 공부 및 정리  (0) 2020.09.16
[iOS] Passing Data Between View Controllers  (0) 2020.09.03