[iOS] Swift Concurrency vs Combine Framework (RxSwift) 차이점

Benedicto·2024년 7월 27일
0

iOS

목록 보기
23/29

Swift Concurrency와 Combine / RxSwift는 모두 비동기 프로그래밍을 다루지만, 접근 방식이 다르다. 각각의 장단점이 있으며, 필요와 상황에 따른 더 적합한 방법이 있다.

이 포스트에서는 Combine으로 설명한다.

  • Swift Concurrency: '비동기 처리를 위한 기본적인 방법을 제공' 하여 비동기 작업을 쉽게 관리할 수 있게 해준다.
  • Combine Framework: '데이터 스트림을 처리' 하는 데 더 적합하여 데이터의 변화를 관찰하고, 그에 따라 반응하는 작업을 쉽게 처리할 수 있게 해준다.

Swift Concurrency

@escaping을 활용한 closures 방식의 비동기 처리는 코드가 난해 (복잡/장황/부정확) 하였기에, 이를 async/await 구문을 사용하여 비동기 작업을 처리할 수 있다.
이는 비동기 작업을 쉽게 관리할 수 있게 해준다.

func fetchData() async throws -> Data {
    let url = URL(string: "https://example.com/data")!
    let (data, _) = try await URLSession.shared.data(from: url)
    return data
}

async/await를 사용함으로써, 비동기 코드의 가독성을 높이고 유지보수를 쉽게 해준다.
(즉, 동기식의 코드처럼 작성이 가능)

✅ Swift Concurrency가 적합한 경우

상황설명
네트워크 요청 (REST API)요청을 보내고 한 번만 응답을 받으면 끝남
단순한 비동기 작업파일 다운로드, 데이터베이스 조회, 단일 데이터 요청
직관적인 코드가 필요한 경우async/await로 가독성이 좋음

Combine Framework (RxSwift)

Combine은 데이터 스트림을 처리하는 데 더 적합하다.
애플이 Combine을 개발한 이유는 기존의 NotificationCenter, KVO (Key-Value Observing), Closures (Custom Observable), Delegates 등의 방식은 비동기 데이터를 처리하는 방식이 통일되지 않고 복잡했기 때문에, 이를 하나의 통합된 프레임워크로 개선하려는 목적이었다.

NotificationCenter, KVO (Key-Value Observing), Closures (Custom Observable), DelegatesCombine의 Publisher로 통합 가능
(즉, 데이터 스트림을 활용하면 여러 개의 비동기 이벤트를 일관된 방식으로 처리 가능)

import Combine

let publisher = URLSession.shared.dataTaskPublisher(for: URL(string: "https://example.com/data")!)
let cancellable = publisher
    .map { $0.data }
    .sink(receiveCompletion: { completion in
        print(completion)
    }, receiveValue: { data in
        print(data)
    })

Publisher와 Subscriber를 사용하여 데이터 스트림을 처리할 수 있으며, 이를 통해 데이터의 변화를 관찰하고, 그에 따라 반응하는 작업을 쉽게 처리할 수 있게 해준다. 따라서 Combine은 데이터 스트림을 처리하는 데 매우 유용하다.

✅ Combine이 적합한 경우

상황설명
타이머 이벤트1초마다 값이 갱신되는 경우
WebSocket / 실시간 데이터주식 가격, 채팅 메시지 등 지속적인 데이터 흐름
UI 이벤트 처리버튼 클릭, 텍스트 입력 변경 감지
여러 개의 비동기 데이터 결합combineLatest(), merge(), zip() 등

🔹 Swift Concurrency vs Combine

Swift Concurrency (async/await)Combine Framework
패러다임명령형 (Imperative)선언형 (Declarative)
주요 개념async/await, Task, ActorPublisher, Subscriber, Operator
사용 목적단일 또는 소수의 비동기 작업 수행지속적인 데이터 흐름 처리 (e.g., UI 이벤트, 네트워크 스트림)
데이터 유형단일 값 반환 (async 함수)여러 개의 값 또는 스트림 처리
성능 최적화경량 스레드 기반 (Task 실행)내부적으로 GCD 사용
에러 처리try/catch 기반Failure 타입을 사용한 에러 스트림 처리
가독성동기 코드와 유사한 흐름함수형 프로그래밍 스타일
스레드 관리await 사용 시 자동으로 최적화명시적으로 receive(on:) 사용
사용 예시네트워크 요청, 파일 읽기, 단일 비동기 작업UI 이벤트 처리, 실시간 데이터 스트림

🔹 사용 사례

Swift Concurrency (async/await)Combine (Publisher/Subscriber)
네트워크 요청 (ex: API 호출, JSON 데이터 가져오기)async/await를 사용하여 단순하고 직관적인 코드 작성 가능URLSession.DataTaskPublisher를 사용하면 가능하지만, 필요 이상으로 복잡할 수 있음
파일 읽기/쓰기 (ex: 로컬 파일, Cloud 저장소 접근)async/awaitTask를 사용하여 효율적 처리❌ 파일 I/O 작업에는 적합하지 않음
데이터베이스 쿼리 (ex: Core Data, Realm에서 데이터 가져오기)async/await로 간결하게 처리 가능❌ Core Data와 함께 사용할 수도 있지만, async/await보다 직관적이지 않음
단기 작업 (ex: 특정 작업이 완료된 후 UI 업데이트)✅ 적합 (await로 결과를 받아 UI 업데이트 가능)❌ 적합하지 않음 (여러 단계를 거쳐야 함)
UI 이벤트 처리 (ex: 버튼 클릭, 스크롤 이벤트, 입력 필드 변경 감지)❌ 직접적으로 지원하지 않음@Published, sink(), assign(to:on:) 등을 사용하여 간편하게 처리 가능
실시간 데이터 스트림 (ex: WebSocket, 실시간 센서 데이터, 주가 변동 감지)async 반복문을 사용할 수 있지만, 적합하지 않음Publisher를 통해 이벤트를 지속적으로 감지하고 처리 가능
여러 개의 비동기 작업을 조합 (ex: 여러 개의 API 응답을 하나로 합치기)async let, TaskGroup을 사용할 수 있지만, 데이터 변형 및 조합에는 한계가 있음combineLatest, zip, flatMap 등을 활용하여 여러 데이터를 쉽게 조합 가능
UI 데이터 바인딩 (ex: SwiftUI의 @State@Published 연동)❌ 직접적인 지원 없음 (async 함수 내에서 수동으로 바인딩 필요)✅ SwiftUI와 자연스럽게 연동 가능 (@Published, ObservableObject)
멀티스레딩 및 데이터 경쟁 방지 (ex: 여러 개의 스레드에서 공유 상태 관리)actor를 사용하여 데이터 경쟁 문제를 안전하게 해결 가능❌ 직접적인 해결책 없음 (사용자가 직접 스레드 관리 필요)
백그라운드 작업 수행 (ex: 다운로드, 압축 해제, 백그라운드 연산)TaskTaskGroup을 사용하여 효율적으로 실행 가능❌ 가능하지만 async/await보다 구조적으로 덜 직관적
에러 처리 (ex: 네트워크 에러, 데이터 변환 오류)do-catchtry-await로 직관적이고 간결하게 처리 가능catch(), replaceError(), retry() 등 연산자가 필요하여 비교적 복잡함
기존 iOS 13+ 프로젝트 지원❌ iOS 15 이상에서만 사용 가능✅ iOS 13 이상 지원 가능
SwiftUI 및 UIKit 프로젝트에서 활용✅ SwiftUI의 task modifier와 함께 사용 가능✅ SwiftUI 및 UIKit에서 이벤트 바인딩에 강점

즉, Swift Concurrency는 단순한 비동기 작업에 적합하고, Combine은 이벤트 기반 비동기 흐름을 관리하는데 적합하다.
Swift Concurrency를 기보능로 사용하되, 이벤트 기반 데이터 흐름이 필요하다고 판단되는 순간 Combine을 곁들여 사용하는 것이 최선의 접근 방식인것 같다.

profile
 Developer

0개의 댓글