티스토리 뷰

반응형

 

 

iOS의 built-in framework 중, Combine이 있습니다. 그 중, Future라는 publisher에 대한 기본적인 사용방법 부터, 제한사항, 주의사항과 이를 해결하는 대안 등에 대해서 알아보겠습니다. 🤔

 


Combine framework, Future Publisher 란?

Future Publisher는 클로져를 통해 일정 작업을 수행하고, 그 콜백을 단일 값으로 방출하고 싶을때 사용할 수 있는 Publisher입니다.

클로져 내에서 원하는 작업을 수행 후, 그 결과값을 방출하거나, 필요시 Error를 던질 수도 있습니다. 만약 failure 케이스가 없다면, Failure 타입을 Never로 지정하면 됩니다.

 

 


Future Publisher 기본 사용 예시 및 주의사항 1

// future publisher는 구독자가 있던 없던, 내부 클로져가 실행된다.
let futurePublisher = Future<Int, Never> { callback in
    DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
        debugPrint("futurePublisher value : \(30)")
        callback(.success(30))
    })
}

Future Publisher의 사용 예시인데요, 3초 기다렸다가, 30이라는 정수 값을 방출하는 publisher입니다. 이때 Future Publisher의 특징은 eager한 Publisher라는 점이 있습니다. eager Publisher인 Future Publisher는 구독자가 있던 없던 클로져에서 지정한 작업을 수행하게 됩니다.

예를들면, 현재 futurePublisher의 구독자가 없음에도, 3초 뒤에 실행되는 debugPrint 가 동작하여 로그가 출력됩니다. ("futurePublisher value : 30")

만약 구독자가 없을때 closure 블럭이 실행되는걸 원치 않다면 eager Publisher를 lazy Publisher처럼 동작시켜야합니다. 이때 Deferred Publisher를 활용 가능합니다.

 

 

 


Deferred Publisher를 통해 Future Publisher를 lazy하게 사용하는 방법

// future publisher는 구독자가 있던 없던, 내부 클로져가 실행된다. 
// 이때 Deferred 를 사용 가능하다. (eager publisher -> lazy publisher로 사용하도록 해줌)
let futurePublisher = Deferred {
    Future<Int, Never> { callback in
        DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {
            debugPrint("futurePublisher value : \(30)")
            callback(.success(30))
        })
    }
}

Deferred Publisher는 eager Publisher를 lazy Publisher로 사용하게 해주고, 생성자 인자로, Publisher를 받아서 DeferredPublisher를 반환합니다.

위와 같이 DeferredPublisher로 사용하면, 구독자가 없는 경우, 안의 클로져 작업이 실행되지 않습니다.

 

 


Future Publisher 사용 시, 주의사항 2

위에 Future Publisher를 사용했을때, 클로져 내에서 단 한번씩만 방출을 했는데요, 만약에 하나의 클로져에서 두번의 방출을 시도하면 두번째 부터는 값이 방출되지 않으므로 이를 주의하여 사용해야 합니다.

 


필요한 시점에 closure 내의 여러개의 값을 방출 받는 방법

public struct Effect<A> {
  public let run: (@escaping (A) -> Void) -> Void

  public func map<B>(_ f: @escaping (A) -> B) -> Effect<B> {
    return Effect<B> { callback in self.run { a in callback(f(a)) } }
  }
}

// * 실제 Publisher를 채택한 구현체를 사용하는 것은 아닙니다.
let effectPublisher = Effect<Int> { callback in
    DispatchQueue.main.asyncAfter(
        deadline: .now() + 2,
        execute: {
            callback(30)
            callback(60)
            callback(90)
        }
    )
}

effectPublisher.run { value in
    debugPrint("effectPublisher value : \(value)")
}

위에서 보았듯이 Future Publisher에서는 클로져 내에 단 한번의 값만 방출합니다. 만약 다수의 값을 방출받고 싶다면, closure를 가진 Custom 구현체를 를 만들어서 사용 가능합니다.

Publisher를 준수하는 구현체는 아니지만, run closure를 접근해서 다수의 값을 방출 받을 수 있습니다.

 

 


Subject Publisher로 원하는 시점에 값을 방출 받는 방법

Publisher이기도 한 Subject는 원하는 시점에 값을 방출받고 싶을때 사용할 수 있는 방법 중 하나입니다.

초기값을 가지고 있는 CurrentValueSubject나 초기값이 없는 PassthroughSubject를 사용해서 원하는 시점에 값을 send, 구독자에게 방출할 수 있습니다.

 


지금까지 iOS의 Combine framework 기능 중, Future Publisher에 대한 사용 예시와 주의사항, 해결 방법 등에 대해서 알아봤습니다. 많은 피드백 부탁드립니다. 감사합니다~!

 

Reference

 

Episode #80: The Combine Framework and Effects: Part 1

Let's explore the Combine framework and its correspondence with the Effect type. Combine introduces several concepts that overlap with how we model effects in our composable architecture. Let's get an understanding of how they work together and compare the

www.pointfree.co

 

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함