Combine의 Future Publisher에 대해 정리.
Future와 Promise란 무엇인가?
Future는 아직 존재하지 않을 수 있는 값을 위한 컨텍스트. 일반적으로, 우리는 비동기 작업의 최종적인 완료 또는 실패를 나타내기 위해 Future를 사용함.
Swift는 Combine 프레임워크의 일부로서 Future의 기본 구현을 제공함.
Future는 자신이 감싸고 있는 값의 타입과 발생할 수 있는 오류의 타입을 나타내는 두 가지 타입을 가짐.
위 코드 조각에서는 각각 Int(값의 타입)와 Never(오류의 타입)가 해당됨.
Combine의 영역에서 Future는 하나의 Publisher임.
Future는 Publisher 프로토콜을 채택함. Publisher 프로토콜의 모든 요구사항을 따르며, Publisher와 관련된 모든 작업과 유틸리티를 지원함.
Promise는 Future의 최종 결과를 의미함.
Future는 Promise로 초기화해야함.
Promise도 Combine 프레임워크에 내장되어 있음.
Promise는 본질적으로 단일 Result 매개변수를 받는 클로저임. 그래서 Future에는 콜백 기반의 생성자가 있음.
Promise에 값(Output)을 전달할 때, 우리는 Future를 fulfill한다고 표현함.
Promise에 오류(Failure)를 전달할 때, 우리는 Future를 reject한다고 표현함.
다시 Future에 대해 정리해보자.
Future 란?
- 비동기 작업을 수행한 후 나중에(또는 바로) 그 결과를 publish하는 Publisher.
- Subscriber가 Future Publisher를 subscribe하면, Future는 특정한 작업이 완료된 후 그 단일한 결과 값(Output 또는 Failure)을Subscribe에게 publish함.
- Future를 초기화할 때 Promise를 사용하며, 이 Promise는 Result 매개변수를 받고 Void를 반환하는 클로져임.
- Future는 비동기 작업의 단일한 결과를 publish한 후 다음 두 가지 중 하나로 종료(Subscibers.Completion)됨.
- 완료(.finished): Future가 성공적으로 값을 publish하면, publish가 comletion(.finished)됨. 이 경우 subcriber는 정상적으로 value을 받고 Publisher의 스트림이 정상적으로 종료됨.
- 실패(.failure): 비동기 작업 중 오류가 발생하면, Future는 에러를 발행하고 그 시점에서 스트림이 completion(.failure(Error))됨. Subscriber는 이 에러를 받아 처리할 수 있음.
사용하는법
예시) 2초 후에 랜덤 숫자(1~10사이)를 비동기적으로 생성하기
Future는 Result 타입을 사용해 작업이 성공했을 때 숫자를 발행하고, 구독자는 sink 메서드를 통해 이 값을 받을 수 있음.
func generateAsyncRandomNumberFromFuture() -> Future <Int, Never> {
return Future() { promise in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let number = Int.random(in: 1...10)
promise(Result.success(number))
}
}
}
cancellable = generateAsyncRandomNumberFromFuture()
.sink { number in print("Got random number \(number).") }
Swift Concurrency와의 통합
- Swift 5.5에서 도입된 async-await 문법과 통합하여 Future의 값을 비동기적으로 기다릴 수 있음.
- Future의 value 프로퍼티를 사용하여 await 키워드로 값을 받을 수 있으며, 이는 단일 값을 발행하는 Future에 특히 유용함.
let number = await generateAsyncRandomNumberFromFuture().value
print("Got random number \(number).")
Swift Concurrency로 완전히 대체
- Swift의 async-await 문법을 사용해 Future를 완전히 대체할 수 있음.
- withCheckedContinuation과 같은 함수를 사용해 비동기 작업이 완료된 후 작업을 수행하는 방식으로 Future를 대체할 수 있음.
func generateAsyncRandomNumberFromContinuation() async -> Int {
return await withCheckedContinuation { continuation in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
let number = Int.random(in: 1...10)
continuation.resume(returning: number)
}
}
}
let asyncRandom = await generateAsyncRandomNumberFromContinuation()
참고:
https://developer.apple.com/documentation/combine/future
'비동기와 반응형 > Combine (반응형 프로그래밍)' 카테고리의 다른 글
[iOS] RxSwift <-> Combine (0) | 2024.05.09 |
---|