iOS/Combine

[Combine] Combining Elements from Multiple Publishers 2 - Operator 공부 9

Dev_Pingu 2022. 5. 10. 22:32
반응형

안녕하세요 Pingu입니다.🐧

 

지난 글에서는 Combine의 Publisher 중 Combining Elements from Multiple Publishers로 분류된 것들 중  Collecting and Republishing the Latest Elements from Multiple Publishers 역할을 하는 CombineLatest 시리즈를 알아봤었습니다. 여러 개의 Publisher에서 받은 최신 값을 적절히 처리해서 Downstream으로 전달하는 역할을 했었어요.

 

이번 글에서는 이어서 Combining Elements from Multiple Publishers로 분류된 것들 중 Republishing Elements from Multiple Publishers as an Interleaved Stream 역할을 하는 Merge 시리즈를 알아보도록 하겠습니다.

 

Republishing Elements from Multiple Publishers as an Interleaved Stream

이번에 공부할 Operator를 분류한 이름을 보다보니 Interleave의 뜻을 몰라서 뭔지 좀 알아봤더니...

이런 뜻이 있네요. 즉 여러개의 Publisher들을 하나의 Stream처럼 사용할 수 있게 해 준다는 뜻이겠네요.

  • Merge
  • Merge3
  • Merge4
  • Merge5
  • Merge6
  • Merge7
  • Merge8
  • MergeMany

실제로 Publisher의 이름을 보면 모두 Merge라는 이름입니다. 저번 글에서 봤듯 뒤에 숫자가 늘어나는건 합치는 Publisher의 개수만 늘어나는 차이만 있어서 이번 글에서는 Merge, MergeMany만 보려고 합니다.

  • merge(with other: P)
  • merge(with b: B, _ c: C)
  • merge(with b: B, _ c: C, _ d: D)
  • merge(with b: B, _ c: C, _ d: D, _ e: E)
  • merge(with b: B, _ c: C, _ d: D, _ e: E, _ f: F)
  • merge(with b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G)
  • merge(with b: B, _ c: C, _ d: D, _ e: E, _ f: F, _ g: G, _ h : H)
  • merge(with other: Self)

이번에 Operator는 위와 같이 모두 이름이 merge입니다. 아까 언급한 대로 대부분은 Publisher의 개수만 다르기 때문에 이번 글에서는 merge(with other: P), merge(with other: Self)만 알아보도록 하겠습니다.

 

Merge

먼저 알아볼 Publisher는 Merge 입니다. 정의를 보면 2개의 Upstream Publisher를 합쳐주는 역할을 하는 Publisher라고 합니다.

Merge3, Merge4... 등등은 위 정의에서 Upstream Publisher의 개수만 다릅니다.

merge(with other: P)

Merge Publisher를 활용해서 만든 Operator는 merge(with other: P) 입니다. 이게 이후에 알아볼 merge(with other: Self)와 생김새가 비슷해서 헷갈릴 수 있는데, 여기서 매개변수로 활용하는 타입은 자기 자신과 Failure, Output 타입이 같은 Publisher입니다.

 

일단 정의를 보면 현재 Publisher와 합친 다른 Publisher가 내보내는 값을 Downstream에 전달한다고 되어있네요.

 

이해를 위해 한 번 사용해볼게요.

let firstPublisher = PassthroughSubject<Int, Never>()
let secondPublisher = PassthroughSubject<Int, Never>()

firstPublisher
    .merge(with: secondPublisher)
    .sink(receiveCompletion: { print($0) },
          receiveValue: { print($0) })

firstPublisher.send(1)
secondPublisher.send(11)
firstPublisher.send(2)
secondPublisher.send(12)

// merge(with:) 예제 코드
1
11
2
12

merge(with other: P)는 Upstream의 2개의 Publisher가 값을 내보낼 때마다 새로운 값을 받습니다. 그러니까 그냥 간단하게 2개의 Publisher를 각각 subscribe하는 것과 비슷한 효과를 낼 수 있습니다.

 

간단하네요.

MergeMany

다음으로 알아볼 Publisher는 MergeMany 입니다.

정의를 보면 여러 개의 Publisher를 합치는 역할을 한다고 합니다.

merge(with other: Self)

MergeMany Publisher를 활용해서 만든 Operator는 merge(with other: Self) 입니다.

정의를 보면 동일한 타입의 Publisher를 합쳐서 내보내는 모든 값을 전달하는 역할을 한다고 합니다.

사실 이 Operator는 아까 알아본 merge(with other: P)와 동일하게 사용하면 되므로 넘어가고 MergeMany의 존재 이유를 알기 위한 예제를 살펴보겠습니다.

 

Merge 시리즈는 Merge8 까지 있었는데요 8개보다 더 많은 Publisher를 한 번에 처리하고 싶을 때 MergeMany를 사용하면 됩니다.

 

간단하게 사용해볼게요.

var publishers: [PassthroughSubject<Int, Never>] = []

for _ in 0...20 {
    let publisher = PassthroughSubject<Int, Never>()
    publishers.append(publisher)
}

Publishers.MergeMany(publishers)
	.sink(receiveValue: { print($0, terminator: " ") })

for index in 0..<publishers.count {
    publishers[index].send(index)
}

// MergeMany 예제 코드
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

이렇게 무려 20개의 Publisher를 하나처럼 처리할 수 있습니다.

 

Merge 시리즈는 여러 개의 Publisher가 내보내는 값을 순서에 상관없이 처리하고 싶을 때 사용하면 좋을 거 같아요.

 

이렇게 Combining Elements from Multiple Publishers로 분류된 것들 중 Republishing Elements from Multiple Publishers as an Interleaved Stream 역할을 하는 Merge 시리즈에 대해 알아봤습니다.

 

다음 글에서는 Combining Elements from Multiple Publishers로 분류된 Publisher 중에서 Collecting and Republishing the Oldest Uncomsumed Elements from Multiple Publishers 역할을 하는 Zip 시리즈에 대해 알아보도록 하겠습니다.

 

전체 코드는 여기서 볼 수 있습니다.

 

감사합니다~!

반응형