ios 48일차

bin·2026년 3월 11일

회고

오늘은 RxSwift를 공부했다. 전체적인 사용의 이유, 및 기본적인 사용법에 대해 시간을 두고 천천히 공부했다. 한번에 모든 내용을 이해할 수는 없지만, 실습을 진행하며 조금씩 정리하다보면 어느 순간부터는 해당 개념들을 본인만의 기억으로 가져갈 수 있을 것이라 생각한다.

공부에 관한 기록

오늘은 본격적으로 RxSwift에 대해 공부를 시작했다. 오늘부터 과제를 시작하면 좋지만, 기본적으로 어느정도의 공부를 진행한 후 시작하고 싶었고, 과제의 요구사항을 읽어보았을 때 어떻게 구현을 진행할지에 대해 아직 제대로 그려지지 않아 공부를 좀 더 진행한 후 시작하려고 한다. (아마 이번에는 늦게 시작하여 주말까지 시간을 할애해야하지 않을까 싶다.) 내일 저녁까지는 과제를 시작하는 것이 목표이다. UI 및 Layout에 관해서는 정해진 틀이 없어서 편하게 구현하면 될 것이고 중요한 것은 RxSwift를 어떻게 사용할 지에 관한 구상일 것이다.

RxSwift

1. 이걸 왜 사용할까?

새로운 개념에 대해 공부를 하게된다면 항상 생각하는 문제점이다. 기존의 방식으로도 할 수 있는데 그래서 이걸 왜 사용해야 하는데 ??

  • 기존 방식
    • Closure
    • Delegate

1.1 문제점 - CallBack

비동기 작업이 연속된다면 클로저가 중첩되어 코드가 CallBack의 지옥이 된다. 들여쓰기가 깊어질 수록 가독성이 떨어지며 이로 인해 코드의 실행 흐름을 한눈에 파악하기 어렵다. 또한, 에러 처리에 대해서도 각 단계 별로 진행해야 한다.

1.2 문제점 - 상태 변수의 분산

검색창에 문자를 입력할 때마다 실시간으로 검색하는 기능을 구현한다고 가정한다면, 기능을 위해 상태 변수를 직접 선언하여 사용해야 하며, 타이머 또한 직접 생성하고 관리해야 한다. 또한, 중복 요청 방지 로직도 구현해야 하며 이전 네트워크 요청을 취소하는 로직도 필요하다. 정리하면, 상태변수를 직접 관리해야 하며, 여러 로직이 분산되어 존재하며 즉, 많은 양의 코드를 필요로 한다.

1.3 문제점 - 에러 처리의 분산

앞서 얘기했듯이, 에러 처리 로직이 여러 곳에서 나타나며 중복되는 경우도 발생한다.

2. RxSwift는 ?

위의 문제들을 RxSwift를 사용하면 해결할 수 있다.

2.1 해결 - CallBack

기존에 사용하던 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)

2.2 해결 - 상태 변수의 분산

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이 자동으로 정리
    }
}

상태 변수 선언을 할 필요 없으며 타이머, 중복방지, 요청취소 등 기존의 방식에서는 직접 관리해야 했던 것들이 자동 관리되며, 코드 또한 매우 줄어든다.

3. RxSwift의 핵심

"시간의 흐름 위에서 데이터를 처리한다.
기존의 방식과 RxSwift의 차이는 데이터를 바라보는 관점이다.

  • 기존방식: "현재"의 데이터를 처리
  • RxSwift: "시간이 지나면서 들어오는" 데이터를 처리
    많은 사람들이 얘기하듯이 RxSwift는 수도관에 비유할 수 있다.
[ 수원지 ]   →   [ 파이프 ]   →   [ 수도꼭지 ]
Observable     Operator        Observer
(데이터 생산)    (데이터 가공)      (데이터 소비)

4. 정리

그렇다면 RxSwift는 모든 상황에서 사용하는 것이 정답인가?
이 질문에 대한 대답으로 본인은 "아니다"라고 생각한다.

RxSwift는 기존의 방식에 반해 비동기 작업이 복잡해지면 발생하는 문제들을 획기적으로 줄여주는 것에 초점을 두고 있다. 허나, 단순 호출과 같은 간단한 구현에 관해서는 기존의 방식을 사용하고 여러 API를 호출하거나 상태변수 관리에 문제가 존재한다 등 복잡한 상황에 사용하는 것이 맞다고 생각한다.

  • 기존의 방식은 비동기 작업이 복잡해질수록 CallBack 중첩, 상태 변수 분산 및 관리, 에러 중복 처리 등 문제가 발생한다.
  • RxSwift는 해당 문제들을 파이프라인을 통해 해결한다.
  • RxSwift의 핵심은 "시간의 흐름 위에서 데이터를 처리한다."는 것이다. 이 시간이라는 개념이 매우 중요하다.
  • 단순한 일회성 작업에는 기존의 방식을 적용하는 것이 더 좋을 수 있으며, 값이 계속 변하거나 복잡한 비동기 조합에는 RxSwift를 사용하는 것이 좋을 것이다.

0개의 댓글