Core Data에서 데이터를 효율적으로 불러오고 UI와 동기화하려면 NSFetchedResultsController
를 활용해야 한다.
특히 UITableView 및 UICollectionView와 함께 사용할 때 성능 최적화에 큰 도움이 된다.
문제 상황
Core Data에서 데이터를 불러와 UITableView에 표시할 때 성능 저하 문제가 발생했다.
fetchRequest를 매번 실행하면 데이터가 많아질수록 로딩 속도가 느려진다.
데이터 변경 시 UI가 자동으로 업데이트되지 않는다.
tableView.reloadData()를 자주 호출하면 불필요한 렌더링으로 성능 저하가 발생한다.
해결 방안
NSFetchedResultsController
설정Core Data에서 NSFetchedResultsController를 사용하면, 데이터가 변경될 때 자동으로 UI를 업데이트할 수 있고 불필요한 reloadData() 호출 없이 성능 최적화가 가능하다.
import CoreData class MyDataManager: NSObject, NSFetchedResultsControllerDelegate { static let shared = MyDataManager() private var fetchedResultsController: NSFetchedResultsController<MyEntity>! lazy var persistentContainer: NSPersistentContainer = { let container = NSPersistentContainer(name: "MyAppModel") container.loadPersistentStores { _, error in if let error = error { fatalError("Core Data error: \(error)") } } return container }() private var context: NSManagedObjectContext { return persistentContainer.viewContext } override init() { super.init() setupFetchedResultsController() } private func setupFetchedResultsController() { let fetchRequest: NSFetchRequest<MyEntity> = MyEntity.fetchRequest() fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)] fetchRequest.fetchBatchSize = 20 // 한 번에 가져올 데이터 개수 제한 (성능 최적화) fetchedResultsController = NSFetchedResultsController( fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil ) fetchedResultsController.delegate = self do { try fetchedResultsController.performFetch() } catch { print("Fetch error: \(error.localizedDescription)") } } func getFetchedResultsController() -> NSFetchedResultsController<MyEntity> { return fetchedResultsController } }
UITableView와 자동 동기화
데이터가 변경되면
NSFetchedResultsControllerDelegate
를 통해 자동으로 UI 업데이트가 가능하다.extension MyViewController: NSFetchedResultsControllerDelegate { func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { tableView.reloadData() } }