iOS 개발 기록

[Combine] Subscribe vs Receive 본문

SwiftUI/Combine

[Combine] Subscribe vs Receive

택꽁이 2023. 3. 8. 16:32
728x90
📄

subscribe와 receive

  • 둘 다 Combine에서 Scheduler를 정하는 인스턴스 메소드이다. 그런데 테스트해보니 둘이 내뱉는 결과가 아예 달랐다.
    // 테스트를 위한 코드
    var cancellable = Set<AnyCancellable>()
    let publisher = [1, 2, 3].publisher
    
    publisher
      .map{ num in
        print("map: \(Thread.current)")
        return num
      }
      .subscribe(on: DispatchQueue.global())
      .sink(receiveCompletion: { completion in
        print("completion")
      }, receiveValue: { num in
        print("\(num): \(Thread.current)")
      })
      .store(in: &cancellable)
    subscribe(on: DispatchQueue.global()) 으로 실행했을 때 결과
    receive(on: DispatchQueue.global()) 으로 실행했을 때 결과
  • subscrbe로 받은 데이터는 모두 같은 스레드에서 실행되지만 receive로 받은 요소들은 제각각 실행된다.
  • 참고로 위의 해당 코드를 실행시켜보면 실제로는 sink에서 3번째 print가 뜨기 전에 finished된다. subscribe와 receive의 차이를 통해 그 이유도 추측해볼 수 있을 것 같다.

subscribe와 receive의 정의

  • subscribe : 구독과 취소, 요청에 대한 작업을 수행할 스케쥴러를 지정한다.
  • receive : publisher로 부터 방출하는 요소를 받을 스케쥴러를 지정한다.

→ 뭔차인지 모르겠다.

subscribe vs receive

  • Publisher에서 주석으로 작성된 정의를 보니 조금 더 이해할 수 있었다.
  • subscribe: 업스트림이 요청받을 스케쥴러를 변경한다.
  • receive: 업스트림으로부터 전달받은 요소를 다운스트림에 전달할 스케쥴러를 변경한다. → Combine에서 Publisher와 Subscriber가 데이터를 다루는 과정을 볼 때에 그림의 말풍선의 위치에서 스케쥴러가 변경이 되는게 아닌가 싶다.

말풍선을 확인하자
  • subscirbe(on: DispatchQueue.global()) 을 통해 요청한 데이터는 이미 스레드의 위치를 결정하고 요청했기 때문에 sink를 통해 받는 데이터들의 스레드 위치가 똑같다.
  • receive(on: DispatchQueue.global())를 통해 요청한 데이터는 GCD가 해당 요소마다 스레드를 배정하기 때문에 sink를 통해 받는 데이터들의 스레드 위치가 차이가 있다.

→ 위의 테스트 코드에서는 receive를 통해 받으면 GCD가 스레드를 배정하고, 작업을 처리하는 속도보다 publisher가 마지막 요소를 방출하고 finished를 때리는 속도가 빨라 몇몇 누락되는 요소들이 생긴게 아닌가 싶다. → 때문에 publisher 를 PassthroughSubject로 만들어 send로 값을 주입하면 생략되는 문제가 해결된다.

PassthroughSubject를 receive(on: DispatchQueue.global()) 로 받았을 때

Reference

Publisher | Apple Developer Documentation
Declares that a type can transmit a sequence of values over time.
https://developer.apple.com/documentation/combine/publisher


Uploaded by N2T

'SwiftUI > Combine' 카테고리의 다른 글

[Combine] Combine과 Combine의 구성 요소  (0) 2023.03.08