[WWDC] DiffableDataSource

zoe·2023년 6월 7일
0

WWDC

목록 보기
1/1

WWDC2019 [Advances in UI Data Sources]

iOS13에서 Diffable DataSource와 Compositional Layout 이라는 새로운 컴포넌트가 등장했다.
iOS14부터 새로운 기능을 도입할 수 있는데, 먼저 Diffable DataSource를 살펴보면

  • snapshot 데이터 타입을 통해서 UI상태관리를 간소화 했다.
  • 스냅샷은 고유 섹션과 identifier를 통해 현재 UI 상태를 캡슐화하고
  • 컬렉션뷰를 업데이트할 때 새 스냅샷 생성 후 데이터를 apply하는 방식으로 작동한다.

게다가 추가 작업 없이 그 차이를 계산하고 애니메니션을 자동으로 생성해주기도 한다고 한다.


Diffable DataSource란 무엇인가?

  • 컬렉션뷰를 그리기 위한 데이터를 관리하고, 바뀐 부분에 해당하는 UI를 자연스럽게 업데이트 해주는 객체를 말한다.
  • 기본적으로 DataSource와 역할은 같지만, 이전 뷰와 달라진 부분을 자동으로 알아차리고, 새로운 부분만 다시 그린다는 점이 차이점이다.

Diffable은 무엇을 뜻하는걸까?
뷰의 항목을 업데이트할 때마다 컬렉션뷰가 업데이트된 컬렉션과 이번에 표시된 컬렉션 간의 차이를 자동으로 계산한다는 것을 의미한다.


Diffable DataSource의 장점은?

  1. 애니메이션
    데이터를 추가, 업데이트, 삭제할 때마다 자동으로 데이터 변경 애니메이션이 적용된다.

  2. 자동 데이터 동기화
    UI 데이터의 동기화 부분 대신 앱의 동적인 데이터와 내용에 집중할 수 있다.
    Centralized Truth를 사용하기 때문에 UI와 데이터소스간의 Truth가 맞지 않아 크래시가 발생하는 일이 없음

  3. 코드감소
    전반적으로 더 적은 코드를 작성할 수 있다.


DiffableDataSource를 왜 사용해야 하지?

Diffable DataSource가 나오기 전에도 테이블뷰를 문제없이 그렸는데, 왜 디퍼블 데이터소스를 사용해야 하는걸까?

아마 iOS앱을 개발한다면 테이블뷰를 그리다 아래와 같은 에러를 만난 경험이 있을것이다. 섹션 수가 잘못되어 앱이 강제종료 되는 경우이다.

어쨌든 해당 에러는 데이터의 변경 사항을 수동으로 관리하고 동기화 할때의 문제점을 나타낸다고 할 수 있는데,
이 문제는 tableView.reloadData()를 이용하여 해결할 수 있다.
그런데도 왜 DiffableDataSource가 필요한걸까?

결론부터 말하자면 사용자 경험 때문이다.

reloadData()의 경우 모든 셀을 다시 그리면서 테이블뷰를 한번에 업데이트 하므로 UI가 애니메이션 없이 부자연스럽게 변경된다.
→ 사용자 경험 저하로 이어질 수 있음

하지만 Diffable DataSource와 함께하면 아래와같이 빠르고 매끄럽고 자연스럽게 테이블뷰를 그릴 수 있다는 것이다.


Compositional Layout

compositional layout은 빠르고 유연하고, composable하게 컬렉션뷰를 구현할 수 있는 컬렉션뷰 레이아웃의 한 종류이다.
컴포지셔널 레이아웃은

  • 빠르고
  • 하나의 컬렉션뷰로 다양한 레이아웃을 구성할 수 있으며
  • 정교한 UI를 구축하는데 도움이 되는 섹션별 레이아웃 기능도 포함되어있다.

Compositional Layout 역시 iOS13에서 도입되었고 item, group, section으로 구성되어있다.
하나의 셀을 item, 아이템의 집합을 group, 그룹의 집합을 section이라고 한다.

섹션 스냅샷을 사용하여 뷰를 업데이트 하고 레이아웃을 구성하는 방법까지 공부하고 내 프로젝트에 적용해보았다.


HighwayInfo 휴게소 화면 구조 분석

HighwayInfo를 만들때 휴게소 화면을 어떻게 구현했는지 예시와 함께 설명해보면

휴게소 섹션은 한개의 그룹, 한개의 섹션으로 이루어져 있고

그룹의 가로는 화면의 넓이의 절반, 높이의 1/4정도 된다

이 화면을 그리기 위해

// item
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)

// group
let groupSize = NSCollectionLayoutSize(widthDimension: widthDimension, heightDimension: heightDimension)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])

// section
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuousGroupLeadingBoundary

group의 가로/세로는 각각 0.5, 0.25로 설정하고 horizontal 레이아웃을 적용해주었다.
아이템은 그룹을 꽉 채우도록 fractionalWidth, fractionalHeight를 각각 1.0으로 설정했다.

섹션의 orthogonalScrollingBehavior를 주어 좌우로 스크롤 되는 레이아웃으로 구현해보았다.


Header View 구현

헤더뷰도 Compositional Layout으로 구성 가능한데,
아래 뷰를 구성하기 위해

// header
let titleSupplementary = NSCollectionLayoutBoundarySupplementaryItem(
    layoutSize: titleSize,
    elementKind: "title-element-kind",
    alignment: .top)
section.boundarySupplementaryItems = [titleSupplementary]

이렇게 헤더를 만들고 섹션의 boundarySupplementaryItems 에 지정해주면 된다.


DataSource 구현


위 화면을 그리기 위해 데이터소스를 어떻게 구현했는지 알아보자.

  1. 셀 구성
    먼저, 각각의 셀이 사용할 데이터 타입과 셀을 등록하고, 클로저에 셀의 내용을 구성해주었다.
  1. 데이터소스 구성
    다음으로 데이터 소스를 구성하고 디큐해주면 된다.

여기에서 어려웠던 점은 내앱의 경우 하나의 컬렉션뷰가 세개의 셀을 나타내야 했기 때문에 food, convenience, brandList 모두 등록해주었는데
저장된 데이터를 꺼내 뷰에 나타낼때 item의 타입을 한개로만 정의할 수 없었다는 점이다.

💡 고민하던 중 FoodMenu, ConvenienceList, Brand 모두 Hashable을 채택했다는 점을 깨닫고 item의 타입을 AnyHashable로 적어주어서 해결했다.

  1. 스냅샷 적용
    스냅샷을 적용할때는 새로운 스냅샷을 만들어서 섹션과 아이템을 스냅샷에 append 해주기만 하면 된다. dequeue할때와 마찬가지로 [AnyHasable] 타입의 아이템을 받아서 main 섹션을 업데이트 해주었다.
  1. 뷰에 바인딩

    현재 내 프로젝트에서는 RxSwift를 사용하고 있기 때문에 데이터가 들어올때마다 applySnapShot을 호출해주는 식으로 바인딩 처리를 해줘서 마무리했다.

뷰 완성

그렇게 해서 완성된 뷰가 휴게소 상세보기 화면 이다


왜 CollectionView 만 업데이트하지?

WWDC2020 컬렉션뷰 레퍼런스를 보면서 왜 테이블뷰도 아니고 컬렉션뷰이지? 라는 궁금증이 생겼는데

애플이 컬렉셔뷰의 API만 업데이트하는 이유는 컬렉션뷰가 UITableView같은 인터페이스를 대체하기 때문이라고 생각한다.

iOS14의 경우 Composition Layout을 기반으로 Lists라고 하는 새로운 기능이 추가된 것을 보면 알수있다.

실제로 2020 WWDC를 보면 UICollectionLayoutListConfiguration에 대한 이야기가 나오는데, iOS14부터 사용 가능한 ListConfiguration을 소개하는것을 알 수 있다.

UICollectionLayoutListConfiguration을 사용하면
이렇게 간단한 코드로

이런 테이블 뷰 리트스 뷰를 만들 수 있다고 하니
언젠가는 컬렉션뷰가 테이블뷰를 대체하고, UITableView관련 API들이 deprecated 될 수도 있겠다는 생각이 들었다.

ListConfiguration은 Compositional Layout 위에서 작동하며 UICollectionViewListCell, header, footer, sidebar를 모두 제공한다고 하는데 테이블뷰가 남아있을 이유가 있을까


소감

Diffable DataSource와 Compositional Layout을 처음 사용해보았는데, 너무 만족스럽다.

새롭게 접하는 개념들이라 낯설고 적용하기 어려울것같다는 우려와는 다르게 사용법도 생각보다 쉬웠다.

제일 좋은점은 기존에 extension으로 컬렉션뷰 UICollectionViewDelegate를 채택하고, 관련 데이터소스와 델리게이트 매서드를 정의해준 부분이 없어졌다는 것이다. 코드가 길고 복잡해서 한눈에 알아보기 어려웠는데 DiffableDataSource는 컬렉션뷰 관련 코드를 한곳에서 관리할 수 있어서 가독성이 높아진거같다.

또 달라지는 데이터만 알아서 다시 그려주니 간편하고 UI업데이트가 자연스러운 점도 장점이다.


참고

profile
개발하면서 마주친 문제들을 정리하는 공간입니다.

0개의 댓글