Subscriber에 대해
Subscriber: Publisher로 부터 나오는 '요소의 흐름'을 받는다.
전에 Publisher에서 Publisher의 receive(subscribe:) method를 통해 Publisher와 Subscriber를 연결하고,
연결된 이후에는 Publisher가 Subscriber의 함수를 호출 시킬 수 있다고 했죠
이 연결 과정에 대해서 좀 정리해보겠습니다.
Publisher와 Subscriber의 구독 과정
Publisher와 Subscriber가 연결되고, Publisher가 내보낸 값을 Subscriber가 받고, 완료되어 종료되는 것 까지의 과정을 그림으로 그려보았는데요.
말로 설명하자면,
1. subscriber가 구독하고자 하는 publisher의 subscribe 메서드를 호출하면서 인자로 본인을 보냅니다. (구독할래! 같은 의미)
2. 그러면 publisher의 subscribe내부에서는 publisher의 receive(subscriber)함수를 호출하여, 이 구독자에게 줄 subscription을 만듭니다. 그리고 이를 subscriber의 receive(subscription)을 호출하면서 인자로 전달해줍니다.
=> 그럼 이제 publisher와 subscriber모두 같은 subscription을 갖게 되고 앞으로는 이 subscription이 둘 사이의 중재자, 매개체, 인터페이스가 되어줄겁니다.
3. 그럼 이제 값을 받아와야 할텐데요. 그러기 위해서는 subscriber가 요청해야합니다. 바로 subscription의 request라는 함수를 통해서!
request함수의 인자로 Demand를 보내는데 이는 내(구독자)가 한번에 얼만큼의 데이터를 받을 수 있는지를 의미합니다. (1이면 publisher가 데이터를 한개씩 보내야겠죠?)
4. 이 요청을 받은 publisher는 값을 내보낼 때 subscriber의 receive(input)함수를 호출하여 인자에 Demand 만큼의 값을 담아 보냅니다.
(openCombine을 보니 request메서드에서 subscriber의 receive(input)을 호출하더라고요)
5. publisher가 보낼 값을 다 보내면 이제 다시 subscriber의 receive(completion)함수를 호출해서 완료되었음을 알립니다. (나 다 보냈음! 같은 것)
6. 그럼 이제 연결이 종료됩니다. 연결을 종료할 수 있는 방법은 이것 말고도 subscriber가 subscription의 cancel() 함수를 호출하여 연결(구독)을 끊을 수도 있습니다. (구취인거죠)
+ Publisher가 명시적으로 completion을 보내지 않으면, subscription은 메모리 관리 정책에 따라 메모리에 해제될 때 둘 사이의 연결이 끊기기도 한다고 합니다.
Subscription의 역할
- Demand 관리 : Demand를 초과하지 않는 양의 데이터가 왔는지 확인
- Subscriber의 유지 및 해제 관리: 아무래도 request와 cancel이라는 함수를 통해서 하는 걸 말하는 것 같습니다.
Subscriber를 쉽게 만들어 쓰는 법 == 쉽게 구독하기
근데 위 그림에서 보이는 Subscriber의 메서드 들이 있는데요.
- receive(subscription:)
- receive(input:)
- receive(completion:)
Subscriber를 구현해서 써야한다면, 이 함수들을 다 구현해주어야 하는 문제가 있습니다.
매우 번거로운 일이죠..그래서 애플은 우리가 자체적으로 Subscriber를 구현해서 사용하는 것을 권장하지 않는다고 합니다.
그럼?
Apple: 우리가 Publisher에 Subscriber 만들어주는 메서드 만들어 뒀어~
가 된 겁니다.
바로 sink와 assign이 애플이 제공하는 Publisher를 쉽게 구독(Subscribe)할 수 있는 방법입니다.
- Sink(receive completion:, receiveValue:)
우선 Sink가 인자로 받는 저 두 친구들은 모두 클로저 즉 함수타입인데요. 받은 완료를 어떻게 처리할지, 받은 값을 어떻게 처리할지 클로저에 선언해두면, Publisher로 부터 받은 값을 내가 원하는 대로 처리할 수 있습니다.
따라서 우리는 sink의 인자로 값을 어떻게 처리할지만 넣어주면, 별도의 Subscriber를 만들지 않고도, Publisher로 부터 값을 받아서 쓸 수 있다는 거죠.
sink 내부에서는 sink 자체적으로 만든 subscriber가 사용되고 이는 Sink 타입이라고 합니다.
"sink: Attaches a subscriber with closure-based behavior."
- Assign(to:, on:)
Assign은 새로운 값을 key path에 따라 주어진 인스턴스의 property에 할당하는 일을 합니다. to에 내가 받은 값을 저장하고 싶은 object의 property경로(key path)를 넣고, on에 어떤 object(인스턴스)인지 넣으면, publisher로 받은 값을 object의 property에 저장합니다.
*assign은 항상 반드시 값이 있을 때만 사용할 수 있습니다. 즉, Failure가 Never일 때만 사용가능.
sink와 assign 모두 다른 publisher의 operator들과는 달리, publisher를 반환하는 것이 아니기 때문에
sink에서 처리된 값을 sink 뒤에서 체이닝 식으로 계속 이용할 수는 없습니다. (자세한건 뒤에 operator 설명하면서 더 이해해보기)
'iOS' 카테고리의 다른 글
[Combine] Basics #1 (Combine 개념, Publisher 기초) (1) | 2025.06.18 |
---|---|
[SwiftUI] Image Carousel View 구현하기 (이미지 갤러리 뷰) (1) | 2025.06.01 |
[iOS] Under the hood: SwiftUI (번역 및 정리) (0) | 2025.04.04 |
[iOS] 프로토콜 지향 프로그래밍 (POP) (0) | 2025.04.02 |
[iOS] Network Calls (네트워크 호출) (0) | 2025.03.28 |