Combine(1)

msyou999·2021년 12월 7일
1

Swift

목록 보기
1/3
post-thumbnail

Combine : what?


Apple 공식 문서에 다음과 같이 정의되어 있습니다.

Customize handling of asynchronous events by combining event-processing operators

  • 이벤트 처리 연산자들을 결합하여 비동기 이벤트를 사용자화 합니다?

    무슨말인지는 모르겠지만, 일단 비동기를 다루는 프레임워크라고 생각했습니다.


더 알아보니 RxSwift와 비슷하고, Apple에서 RxSwift를 만들었다고 보면 됩니다. 저는 RxSwift를 써보지 않아서 모르는데, 이해를 돕기 위해 가져와 보았습니다.



다시 개념으로 돌아가서, 컴바인은 비동기를 다룬다고 했는데, swift에 존재하는 비동기 이벤트들은 다음과 같습니다.
즉, 이러한 이벤트들을 커스터마이즈 할 수 있는 것이 Combine 입니다.

  1. Target/Action
  2. Notification Center
  3. URLSession
  4. KVO
  5. Ad-hoc callbacks




Combine : How?

컴바인은 크게 publisher, subscriber, operator로 구성됩니다.

Publisher

  • 발행자, 구독자가 읽을 것을 발행 (Subscription)
  • Output & Failure Type
  • Convenience Publisher : Future, Just, Deffered, Empty, Fail, Record

Publisher는 발행하는 사람! 즉 구독자가 읽을 요소를 만들고 발행하는데, 이때 발행한 것을 Subscription 이라고 합니다.

  • Publisher를 구현하는 방법
let publisher = ["yms2o"].publisher

Publisher를 사용하기 위해 struct 또는 class를 만들거나, 위와 같이 간단하게 만드는 방법이 있는데요. 이외에도 combine framework에서 자체로 내장된 AnyPublisher나 Convenience Publisher를 사용할 수도 있습니다.


신문을 예시로 들어보자면,

신문 출판사 -> Publisher
구독 확인증 -> Subscription
신문 -> Output

이 되겠죠?

Subscriber

  • 구독자, 발행한 것을 receive
  • Input & Failure Type
  • subscribe, sink, assign

Subscriber는 구독자로, Publisher가 발행한 element(output)을 받습니다.

  • Input ? Output?
    subscriber는 Input 타입을 정의하기 때문에, publisher가 발행한 output 타입과 subscriber의 Input 타입이 동일해야 오류가 나지 않습니다.
  • Failure
    Failure 타입의 경우 Error 와 Never로 나뉩니다.
    Error : 에러가 발생할 것임을 명시 ( 또는 에러처리 할 경우 ) Never : 에러가 발생하지 않음을 명시

즉 publisher와 subscriber 생성 시 output type = input type 이어야 하며, Error나 Never를 지정해 주어야 합니다.

신문을 예시로 들어보자면 신문을 구독하는 사람이 될 수 있습니다.

  • Subscriber를 구현하는 방법
  1. subscribe
    publisher와 마찬가지로 Subscribe를 채택하여 class나 struct로 구현하는 방법입니다.

  2. sink(receiveCompletion:receiveValue:)
    closure에서 새로운 값이나 종료 이벤트에 대해 처리합니다. 즉 value나 completion의 새로운 값만 받아서 편하게 처리할 수 있습니다. 세미나 때 보여드린 예제코드처럼 따로 subscriber 프로토콜을 모두 구현하지 않아도 편하게 subscriber를 만들 수 있습니다.

  3. assign(to:on:)
    새로운 값을 keypath에 따라 주어진 인스턴스의 property에 할당합니다. 좀 더 쉽게 설명하자면,

    publisher.assign(to: \.value, on: object)

    위 예시의 경우 새롭게 받은 값을 object의 value에 할당한다는 의미이고, 여기서 to 의 .은 key path expression이며, on의 object는 class만 가능합니다.
    assign은 publisher로부터 받은 값을 주어진 instance(예시에서는 object)의 property에 할당할 수 있도록 합니다. 받는 값이 무조건 있어야 하기 때문에 sink와 다르게 Failure 타입이 Never일 때만 사용이 가능합니다.
    경우에 따라 assign(to:)만 구현하는 경우도 있다고 해서, 해당 내용을 하단 링크에 걸어두었습니다.
    https://cozzin.tistory.com/14


Operator

  • Merge
  • combineLatest
  • Zip

Operator는 서로 다른 스트림을 하나의 스트림으로 합쳐서 사용할 때 유용합니다.

저는 Nams님의 티스토리를 참고하였습니다.

  • Merge

    Merge는 2개의 스트림을 합쳐주는 operator입니다. 들어온 순서대로 바로 스트림을 생성하여 반환해주기 때문에 차례대로 들어온 이벤트를 처리할 수 있습니다.

  • combineLatest

    combineLatest는 두개의 스트림에서 각각 1개씩 받아온 뒤 single tuple로 스트림을 생성합니다. 어느 한쪽에서 이벤트가 생긴다면 새로운 스트림을 생성하여 single tuple을 업데이트 합니다.
    즉 이벤트가 발생할 때마다 스트림이 생성되기 때문에 이벤트를 이용해서 원하는 작업을 할 수 있습니다.

  • zip

    Zip은 combineLatest와 다르게 각각의 스트림에서 같은 횟수의 이벤트를 발생할 때마다 새로운 스트림을 single tuple로 생성합니다. 각각의 스트림에서 이벤트가 발생하더라도 이벤트 횟수가 동일하지 않으면 스트림을 생성하지 않습니다.
    ** 위 그림에서 5 -> 4로 여기고 참고해주시면 됩니다.


combine 동작 구조

지금까지 combine 기초 개념인 publisher, subscriber, operator에 대해 알아보았습니다. 전체적인 data flow는 다음 그림과 같습니다.

위에서 설명했을 때 publisher는 출판사, subscriber는 구독자, subscription은 구독신청(확인증), input(output)은 신문이라고 비교를 했었는데요.

  1. 구독자가 발행자에게 구독 요청(subscribe)를 보냅니다.
  2. 발행자는 요청을 받고, 구독 요청을 승낙한다는 의미로 subscription을 구독자에게 보내줍니다.
  3. 구독자가 element를 요청합니다.
  4. 발행자가 input값을 구독자에게 보냅니다.
  5. 발행자는 모든 element를 보내고 completion을 구독자에게 전달합니다.

또한 그림에서 demand는 subscriber가 요청할 element의 한도를 의미합니다.

.unlimited // 모든 element를 받음
.none // element를 받지 않음
.max(value:) // value 만큼만 받음

즉 publisher가 여러 element를 가지고 있다고 해도 subscriber가 request demand를 어떻게 설정하느냐에 따라 받은 input value의 갯수가 달라집니다.

초기에는 subscriber가 요청해서 publisher가 subscription을 발행해주고, 이후 demand에 따라 publisher가 element를 보내주는 cycle로 동작합니다.



combine(2)에서는 Subject, Cancellable, Scheduler 프로토콜에 대해 알아보도록 하겠습니다.

0개의 댓글