
RxSwift는?
비동기로 발생한 데이터를 Completion handler가 아닌 return 값으로 전달해주는 클래스

Observable 생성
Observable<String>.create() { observer in
observer.onNext("Hello")
observer.onCompleted()
return Disposables.create()
}
Observable 이 방출하는 데이터 타입을 가지는 객체를 생성후 .create() 메서드를 통해 Observer를 등록합니다.
Observable의 생명주기
create()를 통해 생성subscribe()를 통해 사용onNext()를 통해 데이터 전송onCompleted()oronError()를 통해 종료disposed(): 작업 취소
Observable의 메서드
debug()observeOn()subscribe()
Observable의 operators
just()- 단일 데이터를 전달하는 경우, 정석적인 방법을 다 작성하지 않아도 사용하게 해주는
just가 존재합니다.
- 단일 데이터를 전달하는 경우, 정석적인 방법을 다 작성하지 않아도 사용하게 해주는
func foo() -> Observable<String> { return Observable.just("Hello World") }
from(optional:)- 여러 데이터를 전달하고 싶을 때는 from 내부에 배열을 만들어서 전송할 수 있습니다.
func foo() -> Observable<String> { return Observable.from(["Hello", "World"]) }
subscribe

- Observable 객체의 이벤트를 받을 때 subscribe를 사용합니다.
.subscribe { [weak self] event in
switch event {
case let .next(json):
self?.editView.text = json
self?.setVisibleWithAnimation(self?.activityIndicator, false)
case .error(let e):
print("Error: \(e.localizedDescription)")
break
case .completed:
print("All observable's completed!!")
}
}
- event 전체 (onNext, onError, onCompleted)를 받고자 할 때는 위 방식을 사용하고,
- 위 이벤트 중 일부만 받고싶다면 subscribe에서 각각의 closure 파라미터만 가져와서 사용할 수 있습니다.
.observeOn(MainScheduler.instance)- observeOn 은 onNext를 통해 데이터를 받아온 뒤 메인 스레드에서 처리를 해줘야 할 때
DispatchQueue.main.async{}를 통해 메인 스레드에서 처리를 해주지만,observeOn(MainScheduler.instance)를 통해서 이를 생략할 수 있습니다.
- observeOn 은 onNext를 통해 데이터를 받아온 뒤 메인 스레드에서 처리를 해줘야 할 때
map,filter

- subscribeOn: 시작 메서드를 지정
- observeOn: 이후의 스레드를 지정
- scan
Disposable
Observable의 create의 리턴 값으로 나오는 Disposable은 평소에는 사용하지 않습니다.
하지만 특정 observable의 이벤트를 종료 or 끝내야 할 상황이라면 .dispose() 메서드를 통해 종료할 수 있습니다.
만약 어떠한 이벤트들이 동작하는 도중, 뷰가 사라진다면 특정 이벤트를 종료해야 할 수 있다. 이 경우에 외부에 disposable을 담는 배열이나 변수를 선언해둔다면, viewDidDisappear 에서 이벤트를 종료할 수 있게됩니다.
var disposableBag: [Disposable] = []
...
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
disposableBag.forEach { $0.dispose() }
}
...
func makeObservable() {
...
disposableBag.append(disposable)
}
DisposableBag
위와 같이 Disposable 배열을 선언해도 좋지만 해당 기능을 RxSwift에서는 미리 만들어두었습니다.
DisposeBag 객체를 생성하고, append 대신 insert 를 통해 삽입이 가능합니다.
또한 변수를 할당하지 않고, 생성과 동시에 넣고 싶다면 .disposed(by: disposeBag) 을 통해 생성과 동시에 disposeBag에 넣을 수 있습니다.
var disposeBag = DisposeBag()
Observable.create()...
.disposed(by: disposeBag)
Observable 단점
Observable은 이벤트를 방출하는 스트림이며, 외부에서 임의로 이벤트를 주입(push)할 수 없습니다.
외부에서 이벤트를 발생시켜야 하는 경우, Observable 역할까지 포함한 Subject 를 사용해 스트림에 값을 push할 수 있습니다.
Subject
Subject에는 총 4가지 종류가 존재합니다.
1. PublishSubject
특징
- 구독한 이후부터 이벤트를 받음
- 이전 값은 주지 않음
- 실시간 이벤트에 적합
2. BehaviorSubject
특징
- 항상 최신 값 1개를 저장하고 있음
- 구독하면 즉시 최신 값 1개를 먼저 받고, 이후 이벤트도 받음
- 반드시 초기값이 필요하거나, 최소 한 번은 onNext가 되어 있어야 함
- 현재 상태 표현에 적합
3. ReplaySubject
특징
- 지정한 개수만큼 이전 이벤트를 버퍼에 저장
- 구독하면 저장된 이벤트들을 재생해서 먼저 보여줌
- 최근 N개의 이벤트를 새 구독자들도 봐야 할 때 사용
4. AsyncSubject
특징
- completed 될 때까지 값을 모음
- 완료되면 마지막 값 딱 1개만 방출하고 종료
- 완료되지 않으면 아무것도 나가지 않음
- 최종 결과만 의미 있는 작업일 때 사용
Observable vs. Subject
Observable은 흐름입니다. Observable이 이벤트를 방출하면 Subscribe 한 구독자들이 받는 구조입니다.
간단하게 비유를 들자면 Observable은 인터넷 방송입니다. 그저 흘러가고있을 뿐입니다. 시청자(Subscriber)들은 구독(Subscribe)해서 시청만을 하고 방송을 보는 것 밖에 하지 못합니다.
Subject는 방송국 콘솔입니다. 시청자처럼 방송을 볼 수도 있고(Observable), PD 처럼 방송을 송출할 수도 있습니다(Observer).
즉 Subject는 두 가지 역할을 동시에 합니다.
- Observable (구독할 수 있음)
- Observer (onNext로 이벤트를 밀어 넣을 수 있음)
RxCocoa
viewModel.itemsCount
.map { "\($0)" }
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] in
self.itemCountLabel.text = $0
})
.disposed(by: disposeBag)
위처럼 subscribe를 통해 방출된 이벤트를 처리하는 로직을
viewModel.itemsCount
.map { "\($0)" }
.observeOn(MainScheduler.instance)
.bind(to: itemCountLabel.rx.text)
.disposed(by: disposeBag)
이처럼 bind와 UIKit의 extension으로 만든 RxCocoa를 통해 .rx 를 통해서 값을 바인딩 할 수 있습니다.
또한 subscribe에서 순환 참조를 방지하기 위한 [weak self] 캡처 리스트를 사용하지 않아도 순환 참조가 발생하지 않습니다.
catchErrorJustReturn
RxCocoa의 경우 UI와 관련되어 있기 때문에 항상 메인 스레드에서 동작하도록 해야합니다.
만약 에러가 발생한 경우 해당 스트림은 끊어지게 되는데, UI는 그래서는 안됩니다.
그래서 에러가 발생한 경우 끊어지지 않게 값을 내려보낼 수 있도록 하는 메소드가 존재합니다.
viewModel.itemsCount
.map { "\($0)" }
.catchErrorJustReturn("")
.observeOn(MainScheduler.instance)
.bind(to: itemCountLabel.rx.text)
.disposed(by: disposeBag)
위 경우 에러가 발생하면 빈 문자열을 리턴해주도록 합니다.
Driver


Driver 객체는
- 실패하지 않습니다.
- 메인스케쥴러에 이벤트를 전달합니다.
UI는 항상 메인스레드에서 동작해야 합니다.
따라서 Observable을 사용해도 항상 observeOn(MainScheduler.instance) 를 해줘야 하는데, 항상 메인 스레드에서 동작하는 Observable을 Drive 라고 합니다.
asDriver
위의 catchErrorJustReturn 과 observeOn(MainScheduler.instance) 의 경우 UI 관련된 로직의 경우 필수로 들어가야 합니다.
이를 하나로 축약한 메서드가 존재하는데, 이를 asDriver(onErrorJustReturn:) 이라고 합니다.

viewModel.itemsCount
.map { "\($0)" }
.asDriver(onErrorJustReturn: "")
.drive(itemCountLabel.rx.text)
.disposed(by: disposeBag)
asDriver의 리턴 값은 Driver 객체입니다.
Relay
UI와 관련된 스트림의 경우 한 번 끊어지면 (UI 스트림이 아니더라도) 다시 연결할 수 없기 때문에, 끊어지지 않는 것이 중요합니다.
이를 지원하는 것이 RxRelay 라이브러리 내부의 Relay 들입니다.


Relay의 경우 onNext 의 역할을 하는 것이 accept 메서드입니다.
→ relay는 onCompleted 나 onError 가 존재하지 않기 때문입니다.
'Swift' 카테고리의 다른 글
| [ReactorKit] ReactorKit 기본 개념 살펴보기 (0) | 2026.01.20 |
|---|---|
| RxSwift - Observable 생성 (0) | 2026.01.14 |
| ReactiveX Introduction 번역 (0) | 2025.10.01 |
| [Swift] iOS 앱의 라이프 사이클 관리 (0) | 2025.03.18 |
| [Swift] CoreData를 CloudKit에 연동하기 (0) | 2025.02.18 |