티스토리 뷰

반응형

안녕하세요 Pingu입니다.🐧

 

지난 글에서는 Combine의 Operator 중 Selecting Specific Elements로 분류된 것들을 알아봤었습니다. Upstream에서 받은 값들 중 특정 값만 Downstream으로 전달하는 역할을 했었어요.

 

이번 글에서는 Combining Elements from Multiple Publishers로 분류된 Publisher를 알아보려고 합니다.

Combining Elements from Multiple Publishers역할을 하는 Publisher는 아래와 같은 역할로 나눌 수 있습니다.

  • Collecting and Republishing the Latest Elements from Multiple Publishers (CombineLatest)
  • Republishing Elements from Multiple Publishers as an Interleaved Stream (Merge)
  • Collecting and Republishing the Oldest Unconsumed Elements from Multiple Publishers (Zip)

세 개의 분류로 나뉘어져있으니 하나씩 알아보도록 할게요.

이번 글에서는 먼저 Collecting and Republishing the Latest Elements from Multiple Publishers 역할을 하는 CombineLatest 시리즈를 알아보도록 하겠습니다.

 

Collecting and Republishing the Latest Elements from Multiple Publishers

이번에 공부할 Operator들을 분류한 이름을 보니 여러 개의 Publisher의 값을 모으거나 최신 값을 Downstream으로 보내주는 역할을 할 거 같네요. 그럼 먼저 여기에 분류된 Publisher에는 어떤 것들이 있는지부터 알아보겠습니다.

  • CombineLatest
  • CombineLatest3
  • CombineLatest4

그리고 이 Publisher들을 활용해서 만든 Operator는 아래와 같습니다.

  • combineLatest(_ other:, _ transform:)
  • combineLatest(_ other:)
  • combineLatest(_ publisher1:, _ publisher2:, _ transform:)
  • combineLatest(_ publisher1:, _ publisher2:)
  • combineLatest(_ publisher1:, _ publisher2:, _ publisher3:, _ transform:)
  • combineLatest(_ publisher1:, _ publisher 2:, _ publisher3:)

Publisher도 그렇고 Operator도 그렇고 모두 이름이 combineLatest네요. 그래서 헷갈리긴 한데.. 가만히 보면 규칙이 있습니다. 일단 Publisher의 경우 combineLatest, combineLatest3, combineLatest4와 같이 숫자가 증가하는데, 아까 분류된 이름에 Multiple Publisher가 있었는데 여기서 숫자가 아마 몇 개의 Publisher를 처리할 수 있는지를 나타내는 거 같네요.

 

Operator의 경우엔 그에 따라 매개변수로 받는 publisher의 개수가 하나씩 늘어나는 걸 볼 수 있습니다.

 

그럼 하나씩 알아보도록 할게요.

CombineLatest

첫 번째로 알아볼 Publisher는 CombineLatest입니다.

정의를 보면 2개의 Publisher로 값을 받아서 최신 값을 내려보내는 Publisher라고 합니다.

combineLatest(_ other:, _ transform:)

 

CombineLatest를 활용해서 만든 첫 번째 Operator는 combineLatest(_ other:, _ transform:)입니다. 공식문서에 정의가 이상하게 코드로 되어있네요 ㅋㅋㅋ.

 

매개변수로 받은 other라는 Publisher는 현재 upstream 역할을 하는 Publisher와 결합할 Publisher이고 transform 클로저는 두 개의 publisher에게 최신 값을 받았을 때 downstream으로 두 개의 값을 적절히 처리하여 내려보내는 기능을 합니다.

 

간단하게 사용해보면 이해가 빠르게 됩니다.

let firstPublisher = PassthroughSubject<String, Error>()
let secondPublisher = PassthroughSubject<String, Error>()

firstPublisher
    .combineLatest(secondPublisher) { value1, value2 in
        return value1 + value2
    }
    .sink(receiveCompletion: { print($0) },
          receiveValue: { print($0) })

firstPublisher.send("First ")
secondPublisher.send("Second")

secondPublisher.send("Second-2")
firstPublisher.send("First-2 ")

secondPublisher.send(completion: .finished)
firstPublisher.send(completion: .finished)

// combineLatest(_ other:, _ transform:) 예제 코드 결과
First Second
First Second-2
First-2 Second-2
finished

위 코드를 보면 두 개의 Publisher 모두가 값을 내보내기 전에는 Downstream에 아무것도 전달되지 않습니다. 즉 두 개의 Publisher에서 값을 하나 이상 받은 이후부터 값을 받을 때마다 downstream에 값이 전달되는 걸 볼 수 있어요.

 

또한 두 개의 Publisher가 모두 complete 되어야 finish 되는 것을 볼 수 있습니다.

combineLatest(_ other:)

CombineLatest를 활용해서 만든 두 번째 Operator는 combineLatest(_ other:)입니다. 정의를 보면 2개의 Publisher에서 값을 하나 이상 받으면 각각의 Publisher가 내보낸 값 중 최신 값 쌍을 튜플 타입으로 Downstream으로 내려보내는 역할을 한다고 하네요.

 

방금 알아본 combineLatest(_ other:, _ transform:)에서는 값을 직접 다룰 수 있었는데, 이번 건 튜플 타입으로만 내려보낼 수 있습니다. 공통점은 두 개의 Publisher가 모두 complete 되어야 complete 된다는 점입니다.

 

간단하게 사용해보면 아래와 같습니다.

let firstPublisher = PassthroughSubject<String, Error>()
let secondPublisher = PassthroughSubject<String, Error>()

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

firstPublisher.send("First ")
secondPublisher.send("Second")

firstPublisher.send("First-2")

secondPublisher.send(completion: .finished)
firstPublisher.send(completion: .finished)

// combineLatest(_ other:) 예제 코드 결과
("First ", "Second")
("First-2", "Second")
finished

2개의 Publisher가 내보낸 값을 튜플 타입으로 잘 내려보내는 것을 볼 수 있습니다.

CombineLatest3

다음으로 알아볼 Publisher는 CombineLatest3입니다. 아까 알아본 CombineLatest가 처리하는 Publisher의 수가 2개였다면 CombineLatest3는 3개의 Publisher의 값을 처리해서 Downstream으로 내려보냅니다.

combineLatest(_ publisher1:, _ publisher2:, _ transform:)

 

CombineLatest3을 활용해서 만든 첫 번째 Publisher는 combineLatest(_ publisher1:, _ publisher2:, _ transform:)입니다. 아까 알아본 combineLatest(_ other:, _ transform:)과 동일한데 Publisher가 하나 더 늘어난 차이밖에 없습니다.

 

동일하게 세 개의 Publisher에서 값을 하나 이상 받은 순간부터 Downstream으로 값을 내려보내며, 3개의 publisher가 모두 complete 되어야 finish 됩니다.

 

아래와 같이 사용할 수 있어요.

let firstPublisher = PassthroughSubject<String, Error>()
let secondPublisher = PassthroughSubject<String, Error>()
let thirdPublisher = PassthroughSubject<String, Error>()

firstPublisher
    .combineLatest(secondPublisher, thirdPublisher) { value1, value2, value3 in
        return value1 + value2 + value3
    }
    .sink(receiveCompletion: { print($0) },
          receiveValue: { print($0) })

firstPublisher.send("First ")
secondPublisher.send("Second ")
thirdPublisher.send("Third")

secondPublisher.send("Second-2 ")

firstPublisher.send(completion: .finished)
secondPublisher.send(completion: .finished)

thirdPublisher.send("Third-2")
thirdPublisher.send(completion: .finished)

// combineLatest(_ publisher1:, _ publisher2:, _ transform:)  예제 코드 결과
First Second Third
First Second-2 Third
First Second-2 Third-2
finished

위와 같이 간단하게 사용할 수 있습니다. 위 코드를 보면 firstPublisher, secondPublisher가 completion을 전달한 이후 thirdPublisher에서 값을 내보냈을 때도 각각의 Publisher의 최신 값을 처리해서 Downstream으로 전달한 것을 볼 수 있습니다.

combineLatest(_ publisher1:, _ publisher2:)

CombineLatest3을 활용해서 만든 두 번째 Publisher는 combineLatest(_ publisher1:, _ publisher2:) 입니다. 얘는 3개의 Publisher에게서 하나 이상의 값을 받은 이후부터 각각의 Publisher에서 받은 최신 값을 튜플로 만들어서 Downstream에 전달하는 역할을 합니다.

 

사용은 아래와 같이 할 수 있습니다.

let firstPublisher = PassthroughSubject<String, Error>()
let secondPublisher = PassthroughSubject<String, Error>()
let thirdPublisher = PassthroughSubject<String, Error>()

firstPublisher
    .combineLatest(secondPublisher, thirdPublisher)
    .sink(receiveCompletion: { print($0) },
          receiveValue: { print($0) })

firstPublisher.send("First ")
secondPublisher.send("Second ")
thirdPublisher.send("Third")

secondPublisher.send("Second-2 ")

firstPublisher.send(completion: .finished)
secondPublisher.send(completion: .finished)

thirdPublisher.send("Third-2")
thirdPublisher.send(completion: .finished)

// combineLatest(_ publisher1:, _ publisher2:)  예제 코드 결과
("First ", "Second ", "Third")
("First ", "Second-2 ", "Third")
("First ", "Second-2 ", "Third-2")
finished

CombineLatest4

마지막으로 알아볼 Publisher는 CombineLatest4입니다. 아마 예상하셨을 텐데, 얘는 4개의 Publisher의 값을 처리해줍니다.

combineLatest(_ publisher1:, _ publisher2:, _ publisher3:, _ transform:)

CombineLatest4를 활용해서 만든 첫 번째 Operator는 combineLatest(_ publisher1, _ publisher2, _ publisher3, _ transform:)입니다. 아까 알아본 combineLatest(_ other:, _ transform:), combineLatest(_ publisher1:, _ publisher2:, _ transform:)과 동일하게 동작하지만 이번에는 publisher가 4개라는 차이점만 있습니다.

 

Publisher가 4개라는 점을 제외하고는 모두 동일하니 사용 코드는 넘어가도록 할게요.

하지만 혹시라도 궁금하시다면 여기를 참고해주세요.

combineLatest(_ publisher1: , _ publisher2:, _ publisher3:)

CombineLatest4를 활용해서 만든 두 번째 Operator는 combineLatest(_ publisher1:, _ publisher2:, _ publisher3:)입니다. 얘도 아까 알아본 combineLatest(_ other:), combineLatest(_ publisher1:, _ publisher2:)와 동일한데 이번에는 Publisher가 4개라는 차이점만 있습니다.

 

Publisher가 4개라는 점을 제외하고는 모두 동일하니 사용 코드는 넘어가도록 할게요.

하지만 혹시라도 궁금하시다면 여기를 참고해주세요.

 

 

이렇게 Combine의 Combining Elements from Multiple Publishers로 분류된 것들 중 Collecting and Republishing the Latest Elements from Multiple Publishers 역할을 하는 CombineLatest 시리즈를 알아봤습니다. 사실 Publisher의 개수만 차이나고 모두 동일한 동작 방식을 가지고 있어서 크게 어렵진 않았던 거 같습니다.

 

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

 

이번 글의 전체 코드는 여기에서 볼 수 있습니다.

 

감사합니다~!

 

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함