ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Combine Framework란?
    IOS/Combine 2024. 3. 3. 08:51

    최근 Swift Combine에 대해서 관심이 생겼고 정리겸 지식을 공유하고자 이렇게 글을 작성합니다.

     

    앞으로 주 단위로 콤바인에 대해 알아보는 시간을 가져볼태니 궁금한 점이나 오타, 잘못된 부분은 댓글에 남겨주시면 감사하겠습니다 ㅎㅎ 

     


    Combine은 무엇일까요?

    Definition

    애플에선 Combine framework는 시간에 따라 매번 방출하는 값을 처리하기 위한 선언형 Swift API를 제공한다라고 하는데요, 

    쉽게 와닿지 않지만 최대한 쉽게 설명을 해보겠습니다.

    0초 1초 2초마다 4, 8, 12 란 값을 방출하는 스트림이 있다고 가정한 그림인데요, Combine은  4, 8, 12란 값을 한 번에 받아 처리할 수 있고 아니면 방출 즉시 값들을 받아 작업을 진행 할 수 있습니다. 또한 이런 결과를 Observing하는 기능(Subscriber)을 통해 작업을 비동기적으로 처리할 수 있습니다. 제가 말한 작업중에는 UI업데이트도 있으니 이해가 좀 되셨길 바라면서 계속 진행해볼게요. 

     

    코드를 보면 위 그림은 다음과 같습니다. 주석만 가볍게 봐주세요.

    struct SomeTask {
        let processTime: TimeInterval
        let data: Int
    }
    
    let publihser = PassthroughSubject<SomeTask, Never>()
    var subsciprionts = Set<AnyCancellable>()
    var now = Date().timeIntervalSince1970
    var repeatCount = 1
    
    // 매 1초마다 데이터를 방출
    let task = DispatchQueue.main.schedule(after: DispatchQueue.main.now, interval: .seconds(1.0), {
        if repeatCount < 4 {
            repeatCount += 1
            let task = SomeTask(processTime: Date().timeIntervalSince1970, data: repeatCount * 4 )
            publihser.send(task)
        }
    })
    // 3개의 값을 한번에 처리하는 예제
    publihser
        .collect(3)
        .sink {
    	    // 3개의 값을 배열로 묶어서 print한 것
            print($0.count)
            $0.forEach { someTask in
                print(someTask)
            }
        }
    .store(in: &subsciprionts)
    
    // 방출된 값을 각각 처리하는 예제
    publihser.sink {
        print("Time is", "\(Int($0.processTime - now))")
        print("Data is ", $0.data)
        print("=========================================")
    }
    .store(in: &subsciprionts)

    왼쪽은 3개의 값을 한번에 처리하는 예제/ 오른쪽은 각각 처리하는 예제

    아직 Combine에서 Publisher , Subscription, Subscriber, Operator 는 언급하지 않았으니 이 글에선 설명을 생략하겠습니다.

    중점은 시간에 따라 방출되는 값을 선언적으로 처리한다 입니다. GCD로 1초마다 4씩 증가하는 Data(Value)를 방출했습니다. 이러한 스트림을 가지고 .collect 메서드(방출된 값들을 하나로 묶는 작업을 합니다.)를 사용해 선언적으로 해당 스트림에서 방출되는 값을 처리할 수 있습니다.(.collect는 Combine에서 Operator라 합니다.)

     

    위에서 언급한 Combine요소는 계속해서 블로깅 할테니 기대해 주세요.


    History

    Combine, Apple에서 만든 비동기 프로그래밍을 위한 프레임워크입니다. RxSwift와 동일한 목적을 가지고 개발되었지만 RxSwift는 2012년 MS에서 오픈소스로 개발되었고 Apple은 이 반응형 프로그래밍에 영감을 받아 Combine을 개발했습니다.

    또한 Combine은 비동기 처리를 declarative하게 작성한다 라는 패러다임에 맞게 스케쥴링, 이벤트 처리 및 에러 핸들링을 연속적으로 나열하는 Operator chains형태를 사용하니 코드 복잡성도 크게 줄인 거 같습니다.


    Version

    또한 Combine을 사용할 때에 주의할 점이 iOS버전인데요, 최소 13 버전 이상에서만 지원가능 하다고 합니다. 현재 2024년에 iOS 18 버전이 나올 거 같은 시점인데요. iOS13 버전이라면 2019년이니 Combine도 이쯤에 출시된 거 같네요

    Apple Developer Document


    Benifits

    Apple에서 개발한 만큼 SwiftUI과 같이 최신 프레임워크와 쉽게 Combine을 통해 쉽게 통합할 수 있습니다.

    저 또한 Combine을 프로젝트에 적용시키면서 기능 간 복잡성을 줄일 수 있었습니다. 예로 API 부분에 있어서 Combine을 활용해 쉽게 비동기 통신하고 화면에 반영한 경험이 있어요.  대표적인 예로 아래 Foundation 프레임워크의 URLSession 클래스인데요, 기본적으로 dataTaskPublisher 메서드가 구현되어 있습니다. 

    더보기

    여기서 중요하게 말씀드리고 싶은 부분은 Combine은 Apple에서 만든 거라 별도로 복잡한 코드를 만들지 않아도 비동기 API를 사용하기에 복잡성이 작다는 것입니다. 아래 코드는 가볍게 봐주세요

    DataTaskPublisher가 conform 하는 프로토콜 중에 Publisher가 있는데 이것이 Combine프레임 워크의 요소 중 하나인 Publisher입니다. Publisher 외에 Subsciprtion과 Subscriber가 있는데 이 부분은 글이 길어질 거 같아 다음 Combine 글에 올리겠습니다.

      return URLSession.shared.dataTaskPublisher(for: request)
                .receive(on: DispatchQueue.global())
                .tryMap { output in
                    return try JSONDecoder().decode(KaKaoLocalAPIDTO.self, from: output.data)
                }
                .mapError { error -> KakaoAPIError in
                    switch error {
                    case is URLError:
                        return KakaoAPIError.invalidURL
                    case is DecodingError:
                        return KakaoAPIError.decodeError
                    default: return KakaoAPIError.invalidResponse
                    }
                }
                .eraseToAnyPublisher()

    좀 더 자세히 코드를 보길 원하시는 분은 제가 만든 앱인 Randomdine github repository에서 확인해 주세요.

     


    Combine Vs RxSwift 둘 중 뭐가 나을까?

    해당 항목을 블로깅 하면서 "There is no Silver Bullet"이란 말을 떠올렸는데요, 프레임워크 선택 측면에서는 개인적으로 정답이 없고 적당히 합의점을 찾아 선택해야 한다 생각해요 그래서 아래 사항들을 고려하면 어떨까요?


    성능

    Quickbird studios에서 시행한 테스트에 따르면 Combine은 RxSwift보다 약 40% 빠른 데이터 처리량을 가지고 있다고 하네요. 

    아래 사이트에선 애플이 만든 프레임워크인 만큼 Swift 언어와 최적화가 잘 되어 있다고 말하고 있네요.

    참고사이트: https://quickbirdstudios.com/blog/combine-vs-rxswift/

     

    Combine vs. RxSwift: Should you switch to Combine?

    Roughly one month ago Apple showcased SwiftUI at WWDC 2019. Since we humans can only focus on one new thing, all the hype was reserved for SwiftUI. People almost missed Apple's second big announcement: Combine. In this article, we will take a deep look at

    quickbirdstudios.com

     

    플랫폼 및 최소 요구 사항

    Combine은 iOS 13, macOS 10.15, watchOS 6, tvOS 13 이상에서만 사용할 수 있습니다. 이전 버전의 OS를 지원해야 한다면 RxSwift가 더 적합할 수 있습니다.

     

    프레임워크와의 통합

    SwiftUI나 다른 최신 애플 프레임워크와의 통합이 중요한 프로젝트라면 Combine이 더 나은 선택일 수 있습니다.

     

    커뮤니티 및 지원

    RxSwift는 오랜 기간 동안 사용되어 왔으며, 방대한 커뮤니티와 다양한 학습 자료를 제공합니다. Combine은 비교적 새롭지만, 애플이 지원하며 빠르게 성장하고 있는 커뮤니티가 있습니다.

     

    학습 곡선

    이미 RxSwift나 다른 반응형 프로그래밍 라이브러리에 익숙하다면, RxSwift를 선택하는 것이 더 쉬울 수 있습니다. 반면, Swift와 애플의 최신 기술에 더 집중하고 싶다면 Combine을 배우는 것을 고려해볼 수 있습니다. (개인적으로 RxSwift를 잘 알진 못하지만 Combine과 비슷하게 사용하는 거 같아요 그래서 둘 중 어느 하나만 제대로 알면 금방 사용하다고 하네요.)

     

    프로젝트의 장기적인 유지 보수

    애플이 직접 개발하고 지원하는 Combine을 사용하면, 앞으로의 OS 업데이트와 통합에서 이점을 볼 수 있습니다. 반면, RxSwift는 커뮤니티 기반으로 유지되므로, 애플의 시스템 업데이트에 따라 적응하는 속도가 다를 수 있습니다.

     

    'IOS > Combine' 카테고리의 다른 글

    Combine Operators 1 (transforming)  (0) 2024.04.13
    Combine Cancellable, subscription  (0) 2024.04.07
    Combine - Subscriber 2편  (0) 2024.03.30
    Combine - Subscriber 1편  (0) 2024.03.16
    Combine 구성요소 Publisher  (0) 2024.03.10
Designed by Tistory.