[TIL] DiffableDataSource

Eden·2025년 8월 5일

DiffableDataSource는 Apple이 iOS 13부터 도입한 새로운 방식의 데이터 소스 관리 API로, 기존 UITableViewDataSourceUICollectionViewDataSource의 복잡한 업데이트 로직을 간결하고 안전하게 대체합니다.


기존 방식의 문제점

기존에는 UITableView 또는 UICollectionView에서 데이터를 갱신할 때 다음과 같은 작업이 필요했습니다:

  • insertRows, deleteRows, reloadRows 등을 직접 계산하여 호출
  • indexPath 충돌 발생 가능성
  • 셀 갱신 중 animation 충돌이나 크래시
  • 비동기 처리 시 데이터 동기화 문제

DiffableDataSource의 개념

DiffableDataSource는 스냅샷(Snapshot) 기반으로 작동합니다. UI에 표시할 데이터의 상태를 하나의 snapshot으로 정의하고, 해당 snapshot을 적용(apply)하면 내부적으로 알아서 diff(차이)를 계산하여 UI를 자동으로 갱신합니다.

var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems([item1, item2, item3])
dataSource.apply(snapshot, animatingDifferences: true)

주요 구성요소

1. NSDiffableDataSourceSnapshot

  • 현재 UI에 나타낼 데이터의 "상태"
  • 어떤 section과 어떤 item이 있는지 정의

2. UICollectionViewDiffableDataSource / UITableViewDiffableDataSource

  • 기존 dataSource 역할을 대체하는 객체
  • Snapshot을 통해 UI를 자동 갱신

3. Section Identifier와 Item Identifier

  • 각각 Hashable을 준수해야 함
enum Section {
    case main
}

struct Item: Hashable {
    let id: UUID
    let title: String
}

장점

  • 간결함: 복잡한 indexPath 계산 없이 snapshot만 적용
  • 안정성: 내부적으로 diff 알고리즘이 충돌 방지
  • 성능: 변경된 항목만 최소 단위로 갱신
  • 애니메이션: 자동 처리

사용 예시

let dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView) {
    (collectionView, indexPath, item) -> UICollectionViewCell? in
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath)
    cell.textLabel.text = item.title
    return cell
}

var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems([Item(id: UUID(), title: "Hello")])
dataSource.apply(snapshot, animatingDifferences: true)

주의사항

  • Identifier가 Hashable을 정확히 구현해야 함
  • 항상 전체 snapshot을 다시 구성해야 함
  • 데이터가 변경될 때마다 새로운 snapshot을 apply 해야 함

결론

DiffableDataSource는 UI 갱신을 선언적으로 처리할 수 있게 해주며, 코드의 유지보수성과 안정성을 크게 향상시킵니다. iOS 13 이상을 타겟으로 한다면 적극 사용하는 것이 좋습니다.

profile
iOS Dev

0개의 댓글