스파르타 코딩 클럽 - iOS 스타터 6기/본 캠프

46. 스파르타 코딩 클럽 - RxSwift

seongpil Heo 2025. 5. 9. 11:53

  ReativeX

ReactiveX와 RxSwift 란?

 

ReactiveX

CROSS-PLATFORM Available for idiomatic Java, Scala, C#, C++, Clojure, JavaScript, Python, Groovy, JRuby, and others

reactivex.io

 

ReactiveX

An API for asynchronous programming with observable streams

 

→ ReactiveX 는 옵저버블 스트림으로 비동기 프로그래밍을 돕는 API입니다.

ReactiveX는 이전 강의들에서 배운 비동기 프로그래밍과 옵저버 패턴을 사용하기 쉽도록 돕는 라이브러리입니다. 데이터의 변화에 반응하는 프로그래밍을 하게 되어 반응형 프로그래밍 이라고도 합니다.

Microsoft 사에서 만든 라이브러리로, ReactiveX를 적용한 Swift 라이브러리를 RxSwift라고 합니다.

RxSwift, RxJava, RxPython 등 웬만한 메이저 언어들에 다양하게 지원됩니다. 따라서 다른 플랫폼의 개발자와도, ReactiveX의 개념을 가지고 함께 소통을 할 수가 있습니다. ReactiveX는 iOS 개발자, 안드로이드 개발자뿐만 아니라 서버 개발자, 게임 개발자 등 다양한 분야의 개발자들이 애용하는 라이브러리로, 가독성이 좋은 코드와 유지보수가 좋은 코드를 작성하는 데 도움을 줍니다.


  Observable

▪️ Observable 개념

Observable = 관측 가능한 대상

Observable과 Observer

Observable 은 관측 가능한 대상이며, 이벤트와 데이터를 방출하는 클래스입니다.
Observable에서 이벤트를 방출하면, 이를 구독하고 있던 구독자(=관찰자)들이 그에 반응하여 어떠한 로직을 수행합니다.
Observable을 구독하는 것을 subscribe라고 하며, 이를 구독하고 관찰하는 관찰자를 Observer라고 합니다.
예를 들어, Observable을 구독하고 있는 구독자가 “나는 Observable에서 정수 값이 방출되어 나오면, 그 값에 2를 곱해서 사용할래”라는 세팅을 마쳐놓았고, Observable에서 3이라는 값이 방출되면, Observer는 6이라는 값을 사용하게 되는 것이죠.

Observable 은 데이터가 흐르는 Stream이다.

Observable 은 데이터가 흐르는 Stream이라고 표현하기도 합니다. Stream의 사전적 의미를 살펴보면 시냇물, 흐름, 줄기라는 의미를 갖습니다.
Observable 은 일반적으로 선언하는 변수와 다르게 스트림의 성질을 갖기 때문입니다.
let name = “Louis”
var mbti = “ESFJ”
이렇게 선언한 값들은 한 번 값을 가지면 그 값 자체로 의미를 갖습니다. 하지만 Observable 은 계속해서 새로운 값을 “방출” 해 낼 수 있습니다. 그리고 이를 구독한 구독자들은 값이 방출되었을 때, 그것에 곧바로 반응을 합니다.

 

아래는 Observable 이 방출하는 이벤트에 대한 그림입니다.

 

Observable에서 이벤트(값)를 방출할 때는 상태를 함께 방출합니다.

  • onNext : 정상적인 데이터 방출
  • onError : 에러 방출
  • onCompleted : 옵저버블의 종료 방출

예를 들어 1초 간격으로 값을 방출하는 Observable을 선언할 수도 있습니다. 그렇기 때문에 Observable 은 데이터의 흐름이며, 시간적인 개념이 포함됩니다.


  Observable 예제 코드

1. 기본적인 Observable의 생성 - Observable.create()

import UIKit
import RxSwift

class ViewController: UIViewController {
    // 구독을 끝낸 뒤 구독을 해제하기 위한 diseposeBag.
    let disposeBag = DisposeBag()

    override func viewDidLoad() {
        super.viewDidLoad()
        test()
    }

    func test() {
        // 옵저버블 생성
        let nameObservable: Observable<String> = Observable.create { observer in
            // 순서대로 "Louis", "Mike", "Eric" 이라는 값을 방출하도록 함.
            observer.onNext("Louis")
            observer.onNext("Mike")
            observer.onNext("Eric")
            
            // Disposables.create() 를 작성함으로써 옵저버블 생성 완료.
            return Disposables.create()
        }
        
        // subscribe 로 observable 구독.
        // onNext 안에는 정상적으로 값을 받아보았을 때 값을 어떻게 사용할 것인지 코드 작성.
        nameObservable.subscribe(onNext: { value in
            print("이름: \(value)")
        }).disposed(by: disposeBag) // observable 이 종료되었을 때 구독을 해제할 disposeBag.
    }
}

실행 결과

 

2. 1초마다 정수를 방출하는 Observable 생성 예시

func test2() {
    // 1초마다 값을 방출하는 옵저버블.
    // MainScheduler.instance 는 메인 쓰레드를 의미.
    let someObservable = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)
        .take(5)  // RxSwift 제공 함수. 스트림에서 5개의 항목만 방출되도록 함.
    
    // 구독
    someObservable.subscribe(onNext: { value in
            print("방출된 값: \(value)")
        }, onCompleted: {
            print("Completed")
        })
        .disposed(by: disposeBag)
    
    // 옵저버블 구독은 비동기적으로 작업을 하므로, 아래 print 문이 먼저 찍히게 됨.
    print("Hello")
}

실행 결과


  Single

▪️ Single 이란

옵저버블 중에서, 오직 하나의 값만을 방출하는 옵저버블을 Single이라고 합니다.

  • onSuccess: 옵저버블의 onNext 와 동일
  • onFailure: 옵저버블의 onError 와 동일 

  Single 예제 코드

func test3() {
    // Single 생성
    let single = Single.create { observer in
        observer(.success("Seongpil"))
        return Disposables.create()
    }
    // Single 구독
    single.subscribe(onSuccess: { value in
        print(value)
    }).disposed(by: disposeBag)
}

실행 결과


  Subject

▪️ Subject 란

옵저버블 중에서 외부에서 값을 넣어줄 수 있는 옵저버블을 Subject라고 합니다.

  • BehaviorSubject : 초깃값이 있는 Subject. 구독 시 가장 최근에 방출된 값을 받음.

  • PublishSubject : 초깃값이 없는 Subject. 구독 이후로 방출된 값을 받음.


  Subject 예제 코드

1. BehaviorSubject 코드 작성 예시 - 초기값 O

func test4() {
    // BehaviorSubject 생성
    let subject = BehaviorSubject(value: 10)
    
    // subject 구독.
    subject.subscribe(onNext: { value in
        print("값 방출: \(value)")
    }).disposed(by: disposeBag)
    
    // 외부에서 값을 넣어줌.
    subject.onNext(20)
    subject.onNext(30)
}

실행 결과

2. PublishSubject 코드 작성 예시 - 초기값 X

func test5() {
    // PublishSubject 생성
    let subject = PublishSubject<Int>()
    
    // subject 구독.
    subject.subscribe(onNext: { value in
        print("값 방출: \(value)")
    }).disposed(by: disposeBag)
    
    subject.onNext(20)
    subject.onNext(30)
}

실행 결과