안녕하세요🐶
빈지식 채우기의 비니🙋🏻♂️입니다.
지난 글에서는 간단히 Combine에 대해 알아보았습니다.
.
간단히 요약하면 Apple에서 2019년에 만든 프레임워크로서,
RxSwift와 같이 비동기 프로그래밍을 간단하게 처리가 가능하다 입니다.
이번 포스팅에서는 지난 글에 이어 Publisher, Subscriber에 대해 알아보도록 하겠습니다.
1. 개요
Combine의 핵심은 전부 프로토콜로 이루어져있습니다.
크게 아래와 같이 5개로 확인할 수 있겠네용
- Publihser
- Subscriber
- Subject
- Scheduler
- Cancellable
일단 Publihser 와 Subscriber 그리고 Subscription의 흐름에 대해 먼저 알아보도록 하겠습니다.
이러한 흐름이 있는데 실제 예제를 통해 알아보도록 하겠습니다!
class IntSubscriber: Subscriber {
typealias Input = Int
typealias Failure = Never
// Publisher가 Subscription주면 호출됨
func receive(subscription: Subscription) { // (4)
subscription.request(.max(1)) // (5)
}
// Publisher가 주는 값을 처리
func receive(_ input: Int) -> Subscribers.Demand {
print("Received value : \(input)")
// Publisher에게 한 번 더 달라고 요청
return .max(1) // (5)
}
func receive(completion: Subscribers.Completion<Never>) {
print("Received completion : \(completion)") // (6)
}
}
class CombineTest {
func Test1(){
let intArray: [Int] = [1,2,3,4,5] // (1)
let intSubscriber = IntSubscriber() // (2)
intArray.publisher.subscribe(intSubscriber) // (3)
}
}
1. Int 가 요소인 Array 생성합니다.
2. IntSubscriber 클래스를 참조하는 Subscriber 생성합니다.
3. intSubscriber 가 intArray.publisher 에게 값을 요청하면 달라고 합니다. ( 흐름도 2번 내용 )
4. Publisher가 Subscription을 만들어서 receive 메서드를 통해 Subscriber에게 전달합니다. ( 흐름도 3번 내용 )
5. Subscriber은 request 메서드를 통해 Publisher에게 값을 달라고 합니다. ( 흐름도 4. 5번 내용 )
6. 더 이상 줄 값이 없으면 Completion Event를 전달합니다. ( 흐름도 6번 내용 )
흠.. 이해가 되시나요..?
저 또한 공부하는데 어려움을 많이 겪은 부분입니다 ㅠ.ㅠ
.
Publisher 와 Subscriber에 대해 더 자세히 알아보도록 하겠습니다.
2. Publisher
위에서 잠깐 언급했듯이, Publisher는 프로토콜 입니다.
언어 해석은 무언가를 발행 한다는 의미 같은데.. 정확한 정의는
1. 타입이 시간에 따라 일련의 값을 전송할 수 있음을 선언
2. Publihser는 하나 이상의 Subcriber 인스턴스에게 element를 제공
3. Publihser는 receive(subscriber:) 메소드를 구현해 Subscriber를 accept 함
.
흠.. 무슨 뜻이냐고요..?
지금 포스팅하고 있는 저도 갑자기 햇갈리네요 @.@
좀 더 자세히 알아보도록 하겠습니다.
.
.
만약 Publisher를 직접 구현하고자 한다면,
- Output
- Publisher가 생성할 수 있는 값의 타입
- Failure
- Publisher가 생성할 수 있는 Error 타입
- 만약 Error 타입을 생성하지 않는다면 Never 타입 설정
- receive(subscriber:)
- Publisher 자신을 Subscribe 하는 Subscriber를 받습니다.
이렇게 3가지는 구현을 반드시 해야합니다.
.
개요의 예제와 같이,
설명을 보면 receive를 반드시 호출하라고 하는데..
Subscriber가 Publisher의 Subscribe 메서드를 호출하면,
자신을 receive(subscriber:) 메서드를 통해 Publisher에게 알립니다.
.
무슨 말씀인지 모르겠다고요..? 저도요 ㅎㅎ 그니까! 결론은
.
Publisher는 자신을 Subscribe 한 Subcriber에게 값을 보내는 프로토콜
.
이라고 정리하면 될 것 같습니다.
3. Subscriber
Publihser와 마찬가지로 Subscriber 역시 프로토콜입니다.
Publihser로부터 Input을 받을 수 있는 타입을 선언하는 프로토콜
.
이것도 역시 바로 코드로 확인해보도록 하겠습니다.
위의 예제처럼 Intsubscriber를 만들었는데,
그때처럼 직접 구현을 하기 위해서는 아래와 같은 것들을 필수적으로 구현해야 합니다.
- Input
- Publisher에게 받는 값의 타입
- Failure
- Publisher에게 받는 Error 타입
- 수신하지 않을 경우, Never 타입 지정
- receive(subscription:)
- Publisher가 만들어주는 subscription을 받음
- receive(input:)
- Publisher가 주는 값을 받음
- Demand를 반환하는데 이는 값을 더 원하는지에 대한 여부
- receive(completion:)
- Publisher가 주는 completion event 를 받음
❗️여기서 주의❗️
Publisher 의 Output 과 Failure
Subscriber 의 Input 과 Failure
는 반드시 타입이 동일해야한다.
receive(input:) 의 경우 Demand 를 반환하는데 Demand 는 또 뭔가요..? 팍씌..
설명을 보면 Publisher에게 보낸 Request 횟수라고 한다.
즉 Subscriber가 Publisher 에게 값을 달라고 요청할 수 있는데 그런 요청의 휫수라고 할 수 있습니다.
// Publisher가 Subscription주면 호출됨
func receive(_ input: Int) -> Subscribers.Demand {
print("Received value: \(input)")
// Publisher에게 한 번 더 달라고 요청
return .max(1)
// Publisher에게 값 더 이상 안줘도 된다고 알림
// return .none
// Publisher에게 끝없이 값을 달라고 요청
// return .unlimited
}
위와 같이 .max(1)을 반환하면 한번 더 달라고 요청하는 것입니다.
4. Subscription
그럼 마지막으로 Publisher가 만들어서 Subscriber에게 준다고 했던 Subscription 에 대해 알아보도록 하겠습니다.
1. Publisher 와 Subscriber를 연결하는 프로토콜
2. Cancel 의 경우 Subscription 스레드부터 안전해야함
.
위에 예제에서는 이렇게 사용했었습니다!
// Publisher가 Subscription주면 호출됨
func receive(subscription: Subscription) {
subscription.request(.max(1))
}
- Publisher에게 받은 Subscripton의 request(demand:)를 호출하여 Publisher에게 값을 요청
- Demand는 Publisher에게 값을 몇번 더 달라고 요청
- 즉 Subscriber가 Publisher에게 값을 요청할 때 Subscription을 사용
또한 공식문서를 보면,
cancel을 하려면 Subscription 스레드부터 안전해야 한다고 되어 있습니다.
cancel을 할 수 있는 이유는 Subscription의 경우 Cancellable 프로토콜을 채택하고 있기 때문입니다.
실제 Cancellable의 프로토콜을 보면,
이렇게 Subscription에서 cancel()을 구현하지 않으면,
계속해서 Subscription이 Complete 될때까지 메모리에 남아있게 됩니다.
5. 정리
Publisher | Subscriber | Subscription | |
특징 | 요소값이나 Completion event를 Subscriber에게 전달 | Subscription을 통해 Publisher에게 값을 요청 | 1. Publisher와 Subscriber 사이를 연결 2. cancel()을 통해 취소할 수 있으며, 이때 호출될 클로저를 설정할 수 있음 |
이상으로 간단하게 Publisher, Subscriber에 대해 알아보았습니다.
감사합니다.
참고
'iOS 🖥️ > Combine' 카테고리의 다른 글
[Combine] 다양한 Publisher 들 1 ( Just, Future, Deferred ) (0) | 2024.02.08 |
---|---|
[Combine] Combine 이란? (2) | 2024.01.26 |