[swift] RxSwift를 사용한 MVVM 아키텍처 구현 방법

이번 포스트에서는 RxSwift를 사용하여 MVVM 아키텍처를 구현하는 방법에 대해 알아보겠습니다. MVVM은 Model-View-ViewModel의 약자로, 앱의 로직을 뷰로부터 분리하여 관리하고, 데이터 바인딩을 통해 마치 동적인 뷰처럼 작동하는 패턴입니다. RxSwift는 반응형 프로그래밍을 지원하는 라이브러리로, 이를 활용하면 MVVM 아키텍처를 보다 간결하고 효과적으로 구현할 수 있습니다.

1. 프로젝트 환경 설정

먼저, 프로젝트에 RxSwift를 추가해야 합니다. Cocoapods를 사용하고 있다면, Podfile에 다음과 같이 RxSwift를 추가합니다.

pod 'RxSwift', '~> 6.0'
pod 'RxCocoa', '~> 6.0'

그 후에 터미널에서 pod install 명령어를 실행하여 라이브러리를 설치합니다.

2. 모델 생성

MVVM 패턴에서는 모델이 데이터를 관리하고, 뷰와 뷰모델 간의 중재자 역할을 합니다. 우선, 모델을 생성합니다. 예를 들어, 사람을 나타내는 Person 클래스를 다음과 같이 만들어 봅시다.

struct Person {
    let name: String
    let age: Int
}

3. 뷰모델 생성

뷰모델은 모델 데이터를 가공하여 뷰에게 전달하는 역할을 합니다. 뷰모델은 Observable을 사용하여 모델의 데이터 변화를 감지하고, 뷰에게 업데이트를 전달합니다. 이를 위해 RxSwift의 BehaviorRelay를 활용합니다.

import RxSwift
import RxCocoa

class PersonViewModel {
    private let personRelay = BehaviorRelay<Person>(value: Person(name: "", age: 0))
    
    var name: Observable<String> { // 이름 데이터를 관찰하는 속성
        return personRelay.map { $0.name }
    }
    
    var age: Observable<Int> { // 나이 데이터를 관찰하는 속성
        return personRelay.map { $0.age }
    }
    
    // 모델 데이터를 업데이트하는 메서드
    func updatePerson(name: String, age: Int) {
        let person = Person(name: name, age: age)
        personRelay.accept(person)
    }
}

4. 뷰 업데이트

뷰모델에서 데이터를 업데이트하면, 뷰는 이를 감지하여 업데이트를 수행해야 합니다. 예를 들어, UILabel에 이름을 표시하고, 버튼을 통해 모델을 업데이트하는 간단한 뷰를 생각해 봅시다.

import UIKit
import RxSwift
import RxCocoa

class ViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var ageLabel: UILabel!
    @IBOutlet weak var updateButton: UIButton!
    
    private let personViewModel = PersonViewModel()
    private let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 이름 데이터를 뷰에 반영
        personViewModel.name
            .bind(to: nameLabel.rx.text)
            .disposed(by: disposeBag)
        
        // 나이 데이터를 뷰에 반영
        personViewModel.age
            .map { "\($0)" }
            .bind(to: ageLabel.rx.text)
            .disposed(by: disposeBag)
        
        // 버튼 클릭 시 모델 업데이트
        updateButton.rx.tap
            .subscribe(onNext: { [weak self] in
                self?.personViewModel.updatePerson(name: "John", age: 30)
            })
            .disposed(by: disposeBag)
    }
}

위의 코드에서는 RxSwift의 bind(to:) 메서드를 사용하여 뷰에 데이터를 바인딩하고, subscribe(onNext:) 메서드를 사용하여 버튼의 클릭 이벤트를 구독합니다.

마치며

이번 포스트에서는 RxSwift를 사용하여 MVVM 아키텍처를 구현하는 방법을 알아보았습니다. MVVM 패턴은 UI와 비즈니스 로직의 분리를 도와주며, RxSwift를 활용하면 데이터 바인딩을 통해 뷰 업데이트를 쉽게 처리할 수 있습니다. RxSwift에 대한 자세한 내용은 공식 문서를 참고하시기 바랍니다.