[swift] RxSwift와 Core Data의 연동 방법

Core Data는 iOS 애플리케이션에서 데이터를 관리하고 영구적으로 저장하기 위한 프레임워크입니다. 반면, RxSwift는 리액티브 프로그래밍을 지원하는 라이브러리로, 비동기적인 이벤트들을 쉽게 처리할 수 있게 도와줍니다. 이번 글에서는 RxSwift와 Core Data를 함께 사용하는 방법에 대해 알아보겠습니다.

1. Core Data 설치

첫째로, 프로젝트에 Core Data를 사용하려면 프로젝트 설정에서 Core Data를 활성화해야 합니다. Xcode에서 프로젝트를 열고, Target을 선택한 후, Capabilities 메뉴로 이동합니다. Core Data 옵션을 켜면 Core Data가 사용 가능해집니다.

2. Core Data 모델 생성

두번째로, Core Data 모델을 생성해야 합니다. Project Navigator에서 프로젝트를 우클릭하고, New File을 선택합니다. Core Data 카테고리에서 Data Model을 선택한 후, 이름을 지정하여 모델을 생성합니다. 모델 생성 후, 리소스 파일에 추가됩니다.

3. Core Data 셋업

셋업을 시작하기 위해, CoreDataManager 클래스를 만들어야 합니다. 이 클래스는 Core Data와의 모든 상호작용을 관리할 것입니다.

import CoreData

class CoreDataManager {
    
    static let shared = CoreDataManager()
    
    private lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "ModelName")
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        }
        return container
    }()
    
    func saveContext() {
        let context = persistentContainer.viewContext
        if context.hasChanges {
            do {
                try context.save()
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }
    
}

위 코드에서 persistentContainer는 Core Data 스택을 초기화하고, 데이터를 저장하고 검색하기 위한 핵심 객체입니다. saveContext는 변경된 내용을 저장하는 메서드입니다.

4. Core Data와 RxSwift의 이벤트 연동

이제 RxSwift를 사용하여 Core Data로부터 이벤트를 받아오는 방법에 대해 살펴보겠습니다.

import RxSwift
import RxCocoa

class ViewModel {
    
    private let coreDataManager = CoreDataManager.shared
    
    let data: Driver<[Entity]> // Entity는 Core Data 모델 객체
    
    init() {
        let fetchRequest: NSFetchRequest<Entity> = Entity.fetchRequest()
        let context = coreDataManager.persistentContainer.viewContext
        
        let fetchedResults = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        
        data = Observable.just(fetchedResults.fetchedObjects ?? [])
            .asDriver(onErrorJustReturn: [])
    }
    
    func saveEntity(name: String) {
        let context = coreDataManager.persistentContainer.viewContext
        if let entity = NSEntityDescription.entity(forEntityName: "Entity", in: context) {
            let newEntity = NSManagedObject(entity: entity, insertInto: context)
            newEntity.setValue(name, forKey: "name")
            coreDataManager.saveContext()
        }
    }
    
}

위 코드에서 ViewModel 클래스는 RxSwift와 Core Data를 연동하기 위한 메서드와 속성을 가지고 있습니다. data는 Core Data로부터 받아온 데이터를 드라이버로 노출시킵니다. saveEntity 메서드는 사용자로부터 입력받은 이름을 가지는 새로운 엔티티를 생성하고, Core Data에 저장합니다.

이제 ViewModel을 사용하여 UI를 업데이트하거나 새로운 엔티티를 저장할 수 있습니다. 예를 들어, 테이블 뷰에서 Core Data의 데이터를 가져오려면 다음과 같이 할 수 있습니다.

class ViewController: UIViewController {

    let viewModel = ViewModel()
    let disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        viewModel.data
            .drive(tableView.rx.items(cellIdentifier: "Cell")) { (row, entity, cell) in
                cell.textLabel?.text = entity.name
            }
            .disposed(by: disposeBag)
    }

}

위 코드에서 tableView는 테이블 뷰 인스턴스이며, 셀 아이덴티파이어는 “Cell”입니다. viewModel.data를 바인딩하여 테이블 뷰의 셀에 Core Data의 데이터를 표시합니다.

이제 RxSwift와 Core Data를 연동하는 방법을 알게 되었습니다. RxSwift를 사용하여 비동기적인 이벤트 처리를 용이하게 하고, Core Data를 통해 데이터를 관리하는 애플리케이션을 개발할 수 있습니다.

참고 자료