[iOS] NSFetchedResultsController를 활용한 성능 최적화

Swiftios
avatar
2025.02.19
·
3 min read

Core Data에서 데이터를 효율적으로 불러오고 UI와 동기화하려면 NSFetchedResultsController를 활용해야 한다.

특히 UITableView 및 UICollectionView와 함께 사용할 때 성능 최적화에 큰 도움이 된다.


문제 상황

Core Data에서 데이터를 불러와 UITableView에 표시할 때 성능 저하 문제가 발생했다.

  1. fetchRequest를 매번 실행하면 데이터가 많아질수록 로딩 속도가 느려진다.

  2. 데이터 변경 시 UI가 자동으로 업데이트되지 않는다.

  3. tableView.reloadData()를 자주 호출하면 불필요한 렌더링으로 성능 저하가 발생한다.

해결 방안

  1. 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
          }
      }
  2. UITableView와 자동 동기화

    • 데이터가 변경되면 NSFetchedResultsControllerDelegate를 통해 자동으로 UI 업데이트가 가능하다.

      extension MyViewController: NSFetchedResultsControllerDelegate {
          func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
              tableView.reloadData()
          }
      }






- 컬렉션 아티클