오늘은 RxSwift를 공부했다. 전체적인 사용의 이유, 및 기본적인 사용법에 대해 시간을 두고 천천히 공부했다. 한번에 모든 내용을 이해할 수는 없지만, 실습을 진행하며 조금씩 정리하다보면 어느 순간부터는 해당 개념들을 본인만의 기억으로 가져갈 수 있을 것이라 생각한다.
오늘은 본격적으로 RxSwift에 대해 공부를 시작했다. 오늘부터 과제를 시작하면 좋지만, 기본적으로 어느정도의 공부를 진행한 후 시작하고 싶었고, 과제의 요구사항을 읽어보았을 때 어떻게 구현을 진행할지에 대해 아직 제대로 그려지지 않아 공부를 좀 더 진행한 후 시작하려고 한다. (아마 이번에는 늦게 시작하여 주말까지 시간을 할애해야하지 않을까 싶다.) 내일 저녁까지는 과제를 시작하는 것이 목표이다. UI 및 Layout에 관해서는 정해진 틀이 없어서 편하게 구현하면 될 것이고 중요한 것은 RxSwift를 어떻게 사용할 지에 관한 구상일 것이다.
새로운 개념에 대해 공부를 하게된다면 항상 생각하는 문제점이다. 기존의 방식으로도 할 수 있는데 그래서 이걸 왜 사용해야 하는데 ??
비동기 작업이 연속된다면 클로저가 중첩되어 코드가 CallBack의 지옥이 된다. 들여쓰기가 깊어질 수록 가독성이 떨어지며 이로 인해 코드의 실행 흐름을 한눈에 파악하기 어렵다. 또한, 에러 처리에 대해서도 각 단계 별로 진행해야 한다.
검색창에 문자를 입력할 때마다 실시간으로 검색하는 기능을 구현한다고 가정한다면, 기능을 위해 상태 변수를 직접 선언하여 사용해야 하며, 타이머 또한 직접 생성하고 관리해야 한다. 또한, 중복 요청 방지 로직도 구현해야 하며 이전 네트워크 요청을 취소하는 로직도 필요하다. 정리하면, 상태변수를 직접 관리해야 하며, 여러 로직이 분산되어 존재하며 즉, 많은 양의 코드를 필요로 한다.
앞서 얘기했듯이, 에러 처리 로직이 여러 곳에서 나타나며 중복되는 경우도 발생한다.
위의 문제들을 RxSwift를 사용하면 해결할 수 있다.
기존에 사용하던 Closure 방식 대신 RxSwift를 사용하면 CallBack처럼 중첩되어 나타나는 것이 아니라 위에서 아래로 읽히는 선형 흐름이 된다. 또한, 에러 처리가 파이프라인의 끝인 한 곳에서 처리된다.
fetchUser(userId: "123")
.flatMap { user in self.fetchPosts(userId: user.id) }
.flatMap { posts in self.fetchComments(postId: posts.first?.id) }
.observe(on: MainScheduler.instance)
.subscribe(
onNext: { comments in
self.updateUI(comments)
},
onError: { error in
self.showAlert(error)
}
)
.disposed(by: disposeBag)
class SearchViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
searchTextField.rx.text.orEmpty
.debounce(.milliseconds(300), scheduler: MainScheduler.instance) // 타이머 자동 관리
.distinctUntilChanged() // 중복 방지 자동
.flatMapLatest { query in APIService.search(query: query) } // 이전 요청 자동 취소
.observe(on: MainScheduler.instance) // 스레드 전환 자동
.bind(to: tableView.rx.items(cellIdentifier: "Cell",
cellType: VideoCell.self)) { _, item, cell in
cell.configure(with: item)
}
.disposed(by: disposeBag) // deinit 불필요 — disposeBag이 자동으로 정리
}
}
상태 변수 선언을 할 필요 없으며 타이머, 중복방지, 요청취소 등 기존의 방식에서는 직접 관리해야 했던 것들이 자동 관리되며, 코드 또한 매우 줄어든다.
"시간의 흐름 위에서 데이터를 처리한다.
기존의 방식과 RxSwift의 차이는 데이터를 바라보는 관점이다.
[ 수원지 ] → [ 파이프 ] → [ 수도꼭지 ]
Observable Operator Observer
(데이터 생산) (데이터 가공) (데이터 소비)
그렇다면 RxSwift는 모든 상황에서 사용하는 것이 정답인가?
이 질문에 대한 대답으로 본인은 "아니다"라고 생각한다.
RxSwift는 기존의 방식에 반해 비동기 작업이 복잡해지면 발생하는 문제들을 획기적으로 줄여주는 것에 초점을 두고 있다. 허나, 단순 호출과 같은 간단한 구현에 관해서는 기존의 방식을 사용하고 여러 API를 호출하거나 상태변수 관리에 문제가 존재한다 등 복잡한 상황에 사용하는 것이 맞다고 생각한다.