Swift - QoS, RxSwift: 스케줄러

2 분 소요


The Complete Guide to Concurrency and Multithreading in iOS 참고


GCD(Grand Central Dispatch)

멀티코어 하드웨어에서, 동시 코드 실행을 지원하기 위한 Apple의 저수준 스레딩 인터페이스

QoS(Quality of Service)

작업의 우선순위를 결정할 때 사용
iOS 앱용 에너지 효율 가이드 참고

QoS 작업 타입과 포커스 작업 수행 시간 비고
User-interactive <ul><li>메인 스레드 작업, 사용자 인터페이스 새로 고침, 애니메이션 수행 등 사용자와 상호 작용하는 작업</li><li>작업이 빨리 진행되지 않으면 사용자 인터페이스가 정지된 것처럼 보일 수 있음</li><li>응답성과 성능에 중점</li></ul> 즉각적으로  
User-initiated <ul><li>저장된 문서를 열기, 사용자가 사용자 인터페이스에서 무언가를 클릭할 때 작업 수행 등 사용자가 시작하여 즉각적인 결과가 필요한 작업</li><li>사용자 상호 작용을 계속하려면 해당 작업이 필요함</li><li>응답성과 성능에 중점</li></ul> 몇 초 이내  
Utility <ul><li>데이터 다운로드 등 완료하는 데 시간이 걸릴 수 있고 즉각적인 결과가 필요하지 않은 작업</li><li>일반적으로 사용자가 볼 수 있는 진행률 표시줄 등</li><li>응답성, 성능 및 에너지 효율성 간의 균형을 제공하는 데 중점</li></ul> 몇 초 ~ 몇 분 사용자와 상호작용이 없을 때
90% 정도는
Utility와 Background로
실행하여 최적화해야 함
background <ul><li>인덱싱, 동기화 및 백업과 같이 백그라운드에서 작동하며 사용자에게 표시되지 않는 작업</li><li>에너지 효율성에 중점</li></ul> 몇 분 ~ 시간 저전력 모드에서는
백그라운드 작업 일시 중지 됨

추가적으로 Default, Unspecified가 있지만 개발자 입장에서 작업을 분류하는 데 잘 사용하지는 않음

RxSwift의 스케줄러

RxSwift 스케줄러 문서 참고

MainScheduler

Serial.
MainThread에서 수행해야 하는 작업을 추상화, 메인 쓰레드에서 스케쥴 메소드가 호출되는 경우 스케쥴링 없이 즉시 작업을 수행

SerialDispatchQueueScheduler

Serial.
특정 dispatch_queue_t에서 수행해야 하는 작업을 추상화, concurrent 디스패치 큐가 전달되더라도 serial로 변환한다고 함

serial 스케줄러는 observeOn에 대한 특정 최적화

MainScheduler는 SerialDispatchQueueScheduler의 인스턴스

ConcurrentDispatchQueueScheduler

Concurrent.
특정 dispatch_queue_t에서 수행해야 하는 작업을 추상화, serial 큐를 전달할 수도 있음

백그라운드 작업에 적합

OperationQueueScheduler

Concurrent.
특정 NSOperationQueue에서 수행해야 하는 작업을 추상화

백그라운드에서 수행해야 하는 더 큰 작업이나, maxConcurrentOperationCount를 사용하여 동시 처리를 미세 조정하려는 경우에 적합

observeOn(), subscribeOn()

observeOn() 과 subscribeOn() 입니다.

3

화살표 색을 잘 봐주시면, observeOn(주황), subscribeOn(파랑), observeOn(분홍) 순으로 쓰여져 있지만 스트림의 시작 부분이 파랑이고, observeOn(주황) 이후부터 주황색에서 동작하고, observeOn(분홍) 이후부터 분홍색이 됨

그냥 슥 보면 음? subscribeOn 굳이? 순서만 헷갈리게 하고 왜 이럼? 싶은데

생각해 보니 observeOn만 가지고는 해당 Observable의 처음을 바꿀 수 없는 듯

  • subscribeOn()
    • 특정 스케줄러에서 작업을 수행하도록 Observable에 지시
    • Observable이 작동해야 하는 다른 스케줄러를 지정하여 이 동작을 변경
  • observeOn()
    • Observable이 지정된 스케줄러의 관찰자에게 알림을 보내도록 지시
    • Observable이 관찰자에게 알림을 보내는 데 사용할 다른 스케줄러를 지정

공식문서 보면 어감이 꽤 다르긴 하네요

someObservable
  .subscribe(on: MainScheduler.instance)
  .do { 로딩   애니메이션 작업 }
  .observe(on: ConcurrentDispatchQueueScheduler(qos: .utility))
  .flatMap(네트워크 요청)
  .observe(on: MainScheduler.instance)
  .subscribe {
    로딩 끝내기  UI 작업
    결과 보여주기
  }
  .disposed(by: disposeBag)

간단하게 코드로 보면 요런 느낌일 듯
우선 메인에 subscribeOn 해서 로딩 중 애니메이션 띄우고, 그 뒤부터는 백그라운드에서 observeOn하고, 작업 끝나면 다시 메인에서 결과 보여주기



굿


댓글남기기