Combine #13: 자원 관리
I’m ready to translate the text for you, but it looks like the content to be translated wasn’t included in your message. Could you please provide the text you’d like translated (keeping the source line at the top as you’ve shown)? Once I have the full content, I’ll translate it into Korean while preserving all formatting, markdown, and code blocks.
share()
Combine의 대부분 Publishers는 파이프라인만 설명하는 struct이며, 공유 상태를 저장하지 않습니다. 데이터를 유지하는 살아있는 인스턴스가 생성되는 것이 아니라, 누군가 구독할 때 흐름이 어떻게 생성될지를 설명하는 값이 생성됩니다. 따라서 각 구독은 새로운 퍼블리시 시퀀스를 시작합니다(즉, 자체 작업을 새로 시작합니다).
share()는 multicast(_:)와 PassthroughSubject 위에 구현된 Publisher.Share를 반환하며, 원본 Publisher에 대한 단일 구독을 생성하고 이를 여러 구독자 간에 공유합니다. Combine이 내부적으로 구독자에 대한 참조를 유지하기 위해 클래스를 사용하기 때문에 공유 상태가 있다고 말합니다.
let shared = URLSession.shared
.dataTaskPublisher(for: URL(string: "https://ejemplo.com")!)
.map(\.data)
.share()
let subscription1 = shared.sink { /* … */ }
let subscription2 = shared.sink { /* … */ }
// Sólo se hace una vez la petición web y el resultado se comparte
// por ambas suscripciones
share()가 첫 번째 구독을 받으면 입력 Publisher의 작업을 시작합니다. 이로 인해 다른 구독이 발생하기 전에 흐름이 종료될 수 있으며(종료 이벤트를 발행), 그런 경우 새로운 구독은 종료 이벤트만 받게 됩니다.
let shared = URLSession.shared
.dataTaskPublisher(for: URL(string: "https://ejemplo.com")!)
.map(\.data)
.share()
let subscription1 = shared.sink { /* … */ }
var subscription2: AnyCancellable? = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
subscription2 = shared.sink { /* … */ } // solo recibe el evento de fin
}
multicast(_:)
multicast(_:)는 Subject를 사용하여 여러 구독자에게 값을 방출하고 ConnectablePublisher를 반환합니다. 이는 입력 Publisher에 대한 구독이 connect() 신호를 받을 때까지 이루어지지 않음을 의미합니다.
// Subject para emitir eventos del multicast.
// Recibe del flujo de entrada
let subject = PassthroughSubject<Data, URLError>()
// Se crea el Publisher multicast, envolviendo el subject
let multicasted = URLSession.shared
.dataTaskPublisher(for: URL(string: "https://ejemplo.com")!)
.map(\.data)
.multicast(subject: subject)
let subscription1 = multicasted.sink { /* … */ }
var subscription2: AnyCancellable? = nil
// Crear una segunda suscripción al multicast
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
subscription2 = multicasted.sink { /* … */ }
}
// Suscribir el multicast al dataTaskPublisher
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
let cancellable = multicasted.connect()
}
multicast(_:)가 ConnectablePublisher를 반환하기 때문에, 첫 번째 구독이 발생하자마자 입력 Publisher에 자동으로 연결되도록 autoconnect()를 사용할 수도 있습니다.
한 번만 작업을 수행하고 값을 방출하면 되는 상황에서는 CurrentValueSubject를 사용할 수 있습니다.
Future
Future는 class(struct가 아니라)로 구현된 Publisher이며, Future.Promise를 받는 클로저를 받습니다. 그 클로저는 단 하나의 값을 생성하고 종료됩니다. 클로저 내부에서 작업이 실행되고, 작업이 끝나면 결과 또는 오류와 함께 프라미스를 호출합니다.
Future인스턴스를 생성할 때 클로저가 즉시 실행됩니다, 구독자를 기다리지 않습니다.Future는 프라미스의 결과를 저장하고 현재 및 미래의 모든 구독자에게 방출합니다.
let future = Future { fulfill in
do {
let result = try performSomeWork()
fulfill(.success(result))
} catch {
fulfill(.failure(error))
}
}
let subscription1 = future.sink(
receiveCompletion: { _ in },
receiveValue: { value in print("1️⃣", value) }
)
let subscription2 = future.sink(
receiveCompletion: { _ in },
receiveValue: { value in print("2️⃣", value) }
)
복습 질문
Combine의 Publisher, 각 구독이 흐름 작업을 반복합니까?
- 내부 상태를 유지하는 클래스이기 때문입니다.
- 구독당 새로운 스레드를 만들기 때문입니다.
- Publisher가 파이프라인을 설명하는 구조체(
struct)이며 상태를 공유하지 않기 때문입니다. - 구독자가
connect()로 수동 연결해야 하기 때문입니다.
Publisher에서 share()
- 각 구독자에게 흐름의 별도 복사본을 생성합니다.
- 중복된 구독을 취소합니다.
- 원본 Publisher에 대한 단일 구독을 만들고 그 결과를 여러 구독자와 공유합니다.
- Publisher를
Subject로 변환합니다.
흐름이 이미 종료된 후 share()로 공유된 Publisher
- 저장된 이전 값을 받습니다.
- 아무것도 받지 않고, 종료 이벤트만 받습니다.
- 원본 흐름 전체가 다시 실행됩니다.
- 런타임 오류를 일으킵니다.
share()는 어디에서 사용됩니까?
-
Future와Just에서. -
multicast(_:)와PassthroughSubject에서. -
CurrentValueSubject에서. -
DispatchQueue에서.
multicast(_:)와 share() 비교
-
multicast(_:)는Subject가 필요하지 않습니다. -
multicast(_:)는connect()를 호출해야 하는 ConnectablePublisher를 반환합니다. - 각 구독자마다 작업을 반복합니다.
-
share()는 여러 수동 연결을 허용하지만multicast(_:)는 허용하지 않습니다.
multicast(_:)로 만든 ConnectablePublisher에서 autoconnect()
- 첫 번째 구독을 받을 때 Publisher가 자동으로 연결됩니다.
- 구독을 자동으로 취소합니다.
- Publisher를
Future로 변환합니다. - 향후 구독자를 위해 결과를 저장합니다.
share() 또는 multicast(_:)와 같은 다른 Publisher의 Future
- 상태가 없는 Publisher
struct입니다. - 오류만 방출하고 값은 방출하지 않습니다.
- 구독을 받은 후에만 실행됩니다.
- 생성 시 즉시 작업을 수행하고 결과를 모든 구독자에게 저장하는 클래스입니다.
빠른 요약
- Combine의 Publishers는 대부분
struct이며 → 각 구독이 파이프라인을 다시 실행합니다. - **
share()**는 업스트림에 대한 단일 구독을 생성하고 이를 공유합니다. - **
multicast(_:)**는Subject가 필요하고, connectable이므로connect()(또는autoconnect())가 필요합니다. - **
Future**는 작업을 즉시 실행하고 결과를 저장하여 이후 구독자에게 제공하는 클래스입니다.
share(), multicast(_:), **autoconnect()**에 대한 질문과 답변
| 질문 | 답변 |
|---|---|
Publisher에서 share()는 무엇을 하나요? | ✅ 원본 Publisher에 대한 단일 구독을 만들고 그 결과를 여러 구독자와 공유합니다. |
share()로 공유된 Publisher는 흐름이 이미 끝난 후에 이루어지나요? | ✅ 아무것도 받지 않고, 종료 이벤트만 받습니다. |
share() | ✅ multicast(_:)와 PassthroughSubject에서 사용됩니다. |
multicast(_:)와 share()의 차이점은 무엇인가요? | ✅ multicast(_:)는 ConnectablePublisher를 반환하며, connect()를 호출해야 합니다. |
multicast(_:)로 만든 ConnectablePublisher에서 autoconnect()는 무엇을 하나요? | ✅ 첫 번째 구독을 받을 때 Publisher가 자동으로 연결되도록 합니다. |
share()나 multicast(_:)와 같은 다른 Publisher의 Future란 무엇인가요? | ✅ 생성 시 작업을 즉시 실행하고 결과를 모든 구독자에게 저장하는 클래스입니다. |
빠른 요약 (반복)
share()→ 내부 구독자 하나만 존재하고, 값을 공유하며 외부 구독자에게는 종료 이벤트만 전달합니다.multicast(_:)→ ConnectablePublisher를 반환합니다; 전송을 시작하려면connect()(또는autoconnect())가 필요합니다.autoconnect()→ 첫 번째 구독을 받을 때 자동으로 연결합니다.Future→ 작업을 즉시 실행하고 결과를 저장하여 이후 구독자에게 제공합니다.