study record

[RxSwift] Scheduler란? 본문

iOS/RxSwift

[RxSwift] Scheduler란?

asong 2022. 8. 7. 18:27

Scheduler

: 프로세스가 있는 곳의 Context (= thread, dispatchQueue)

특정 코드가 실행되는 Context를 추상화한 것이다.

 

Cocoa에서는 Main Queue를 사용하지만 RxSwift에서는 MainScheduler를 사용한다.

 

 

연산자

  • subscribeOn : Observable의 프로세싱이 어디서 일어나게 할 것인지 결정하는 연산자
  • observeOn : Observer가 Observable을 어디서 observe할 것인지

일반적으로 subscribeOn(:)은 Background Thread에서, observeOn(:)은 Main Thread에서 사용

 

 

observeOn vs subscribeOn

다른 스케줄러에서 작업하고자 한다면 observeOn을 사용한다.

sequence(subscribe method)를 생성하고, 특정 스케줄러에서 dispose를 호출하고 싶다면 subscribeOn(scheduler)를 사용한다.

sequence1
  .observeOn(backgroundScheduler)
  .map { n in
      print("This is performed on the background scheduler")
  }
  .observeOn(MainScheduler.instance)
  .map { n in
      print("This is performed on the main scheduler")
  }

첫번째 map은 백그라운드 스케줄러 위에서 작업하는 것이고, 두번째 map은 메인 스케줄러 위에서 작업하는 것이다.

Sequence의 생성은 subscribe가 호출될 때 시작된다!

구독되지 않으면 observable은 선언만 되어있는 상태이므로 어떤 이벤트도 일어나지 않는다. 따라서 subscribe가 호출되어야만 observable이 생성되는 것이다.

그래서 subscribeOn은 시퀀스가 생성될 때(=subscribe가 호출될 때)의 스케줄러를 지정하는 것이다.

// observeOn과 subscribeOn을 사용한 예제
Observable<Int>.create { observer in
    observer.onNext(1)
    observer.onNext(2)
												
    print("Hi \\(Thread.isMainThread)")

    observer.onCompleted()
    return Disposables.create()
}
.observeOn(MainScheduler.instance)
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background))
.subscribe(onNext: { el in	    
    print("onNext \\(el) \\(Thread.isMainThread)") 
}, onDisposed: {(
    print("dispose \\(Thread.isMainThread)")
)})

/*
	onNext 1 true
	onNext 2 true
	Hi false
	dispose true
*/

observeOn을 메인 쓰레드로 지정하였으므로 구독하는 작업을 메인 쓰레드에서 진행한다.

subscribeOn을 백그라운드로 설정하였으므로 observable을 백그라운드에서 생성하게 된다.

observeOn : operator(map, filter, etc)와 subscribe 작업을 다른 스케줄러에서 사용하고 싶을 때 사용.

subscribeOn : observable을 특정 스케줄러에서 생성하고 싶을 때 사용.

 

 

Scheduler의 종류

Serial Scheduler를 사용한다면 Rx는 직렬적으로 진행한다.

Concurrent Scheduler를 사용한다면, Rx는 동시에 진행한다.

 

1) MainScheduler

  • 메인 쓰레드에서 가장 위에 존재한다.
  • UI와 높은 우선순위 테스크를 진행한다. heavy task는 피해야 한다. (API request등)
  • UI 갱신시 이 스케줄러로 변경하여 사용한다.

2) SerialDispatchQueueScheduler

  • background에서 추출하는 일을 처리할 때 사용한다.
  • 특정 dispatchQueue에서 수행해야하는 작업을 추상화한다.
  • Serial하게 작업을 처리합니다. (사실 MainScheduler도 SerialDispatchQueueScheduler의 일종이다.)
  • (Firebase를 사용할 때 서버의 endpoint에 너무 많은 pressured을 줄일 수 있음)

3) ConcurrentDispatchQueueScheduler

  • SerialDispatchQueueScheduler와 같이 추출하는 일을 처리할 때 사용한다, 단 병렬적
  • 특정 dispatchQueue에서 수행해야하는 작업을 추상화한다.
  • Concurrent하게 작업을 처리한다.
  • (작업량이 많은 일에 사용)

4) TestScheduler

  • 테스트를 위한 것이며, production code에는 사용하지 않는다.
  • RxTest 라이브러리에 존재
let scheduler = TestScheduler(initialClock: 0)
let xs = scheduler.createColdObservable([ next(50, 42),
	next(60, 43),
	completed(70)
])

let res = scheduler.start {
	xs.delaySubscription(30, scheduler: scheduler) 
}

// test
XCTAssertEqual(res.events, [ 
	next(280, 42),
	next(290, 43), 
    completed(300)
])

 

 

참고:

https://sweepty.medium.com/rxswift-scheduler-제대로-알아보기-f2e26aeb829d

https://ios-development.tistory.com/133

https://velog.io/@hansangjin96/RxSwift-Scheduler-작성중

 

'iOS > RxSwift' 카테고리의 다른 글

[RxSwift] Rx Operators (What i frequently used)  (0) 2022.09.04
[RxSwift] Observable이란?  (0) 2022.08.06
Reactive Programming이란?  (0) 2022.07.17
[RxSwift] Driver란?  (0) 2022.03.29
[RxSwift] Subject와 Relay  (0) 2022.03.14