[WWDC 2020] Advances in diffable data sources
안녕하세요 Pingu입니다.🐧
오늘은 WWDC 2020의 Advances in diffable data sources라는 영상을 보고 정리한 글을 써보려고 합니다.
개발을 하는데 하나의 뷰에서 섹션별로 데이터도 쉽게 처리할 수 있는 Diffable Data Source라는 엄청난 게 있다길래 공부해서 저도 써보려고 이번 영상을 보게 되었습니다. 😄
Advances in diffable data sources
이번 영상에서는 iOS 14에서 추가된 diffable data source에 대해 다룬다고 합니다. 엥 더 이전에 나온 관련 영상도 있었네요. 일단 지금 영상이 짧으니까 이거 보고 이전에 나온 영상도 봐야겠네요.
어쨌든 이번 영상에서는 "Emoji Exploer"라는 샘플 앱을 가지고 설명한다고 합니다.
이 앱은 위 움짤을 보면 위에서 부터 3가지 부분으로 나뉩니다.
첫 번째 섹션은 좌우로 스크롤되는 이모티콘 그리드 영역이 있고 두 전째 섹션은 iOS 14에서 추가된 접을 수 있는 스타일의 outline style UI라고 합니다. 그리고 마지막 섹션에는 위에서 보이는 UI는 컬렉션 뷰인데 그 안에 있는 테이블 뷰같이 보이는 영역입니다.
이렇게 iOS 13에서 도입된 Diffable Data Source를 사용하면 새로운 Snapshot 데이터 타입을 추가해서 UI 상태 관리를 단순화할 수 있다고 합니다.
여기서 Snapshot은 고유한 section 및 item identifier를 사용해서 전체 UI 상태를 캡슐화하는 것을 말하는데 이를 사용해서 CollectionView를 업데이트할 때 먼저 현재 UI 상태로 새로운 snapshot을 만들어서 Data Source에 적용한다고 합니다. 이렇게 사용하는 Diffable Data Source를 사용하면 개발자가 추가 코드를 작성하지 않아도 애니메이션이나 변화를 줄 수 있다고 합니다.
이럴 때 사용하는 API들은 아까 글 초반에 언급한 WWDC 2019 영상에서 자세히 다룬다고 하네요..
대신 이번 영상에서는 iOS 14에서 추가된 Diffable Data Source의 새로운 기능인 Section Snapshot, Reordering Support에 대해서 알아본다고 합니다.
Section Snapshots
먼저 Section Snapshots를 알아봅시다!
iOS 14부터 Section snapshots도 추가되었습니다. 이름에서도 알 수 있듯 뭔가 UICollectionView의 섹션에 대한 일을 할 거 같은데요, 역시나 UICollectionView의 단일 섹션에 대한 데이터를 캡슐화한다고 합니다. 이걸 만든 두 가지 이유가 있다고 합니다.
- Data Source를 섹션 단위로 구성할 수 있습니다.
- iOS 14에서 추가된 Outline style UI를 지원하기 위해 필요한 계층적 데이터의 모델링을 허용하기 위함 입니다.
다시 샘플 앱으로 돌아와서 Section Snapshot을 사용해서 앱을 만드는 방법을 살펴보겠습니다.
먼저 위와 같이 수평 스크롤 섹션에서 Section snapshot을 사용해서 해당 섹션의 콘텐츠를 모델링합니다.
다음으로 확장 가능하고 접을 수 있는 Outline-Style 섹션인 두 번째 섹션도 Section Snapshot을 사용해서 모델링합니다.
마지막 섹션 역시 Section Snapshot으로 모델링합니다.
결국 이렇게 되면 현재 앱의 Diffable Data Source는 섹션별로 하나의 Section Snapshot, 즉 총 3개의 Section Snapshot으로 구성됩니다.
몇 가지 API를 살펴보겠습니다. iOS 13에서 도입된 snapshot을 말할 땐 "Snapshot"으로 표기하고 지금 배우고 있는 iOS 14에서 도입된 snapshot을 말할 땐 "Section Snapshot"으로 언급해서 구분하겠습니다.
새로운 Section Snapshot 타입을 살펴보면 제네릭을 사용하는 것을 볼 수 있습니다. 기존 Snapshot과 다르게 identifier가 없습니다. 이는 Section Snapshot이 실제로 어떤 섹션을 나타내는지 모른다는 걸 뜻한다고 하네요.
append API를 사용하면 Section Snapshot에 콘텐츠를 추가할 수 있다고 합니다. append의 매개변수 중에서 items는 추가하려는 콘텐츠를 말하는데, 그럼 parent가 뜻하는 건 뭘까요? parent에 nil이 아닌 값이 제공되면 계층 데이터를 모델링하는데 필요한 상위 하위 관계를 생성할 수 있다고 합니다.
그럼 저렇게 생긴 Section Snapshot을 사용하기 위해 UICollectionViewDiffableDataSource에 두 개의 API도 추가되었습니다.
첫 번째 API는 Section Snapshot과 Section Identifier를 사용하는 "apply"입니다.
두 번째 API인 "snapshot"을 사용하면 특정 섹션의 내용을 나타내는 Section Snapshot을 찾을 수 있다고 합니다.
이제 Snapshot과 Section Snapshot을 함께 사용해서 CollectionView를 구성하는 방법을 자세히 살펴보겠습니다.
일단 위 코드와 같이 Diffable Data Source에 apply 메서드를 사용해서 원하는 순서로 섹션을 추가합니다. 위 코드에서는 recent, top, suggested라는 순서로 섹션이 구성된 것을 볼 수 있어요.
그런 뒤 위와 같이 섹션마다 Section Snapshot을 만들어서 각 섹션에 apply 메서드로 적용해줍니다. 그럼 이제 각 섹션은 각각의 Section Snapshot으로 item을 채우게 될 거예요.
그럼 다음으로 두 번째 섹션이었던 Outline-Style UI를 구성하는 방법을 살펴보겠습니다.
먼저 섹션에 Root 아이템을 추가합니다. 이때 append API를 사용하는 것을 볼 수 있어요. 아까 append의 parent 매개변수에 값이 있으면 계층 구조를 만들 수 있다고 했잖아요? 그래서 위와 같이 Food를 parent로 제공하면 오른쪽에 보이는 UI와 같이 계층 구조를 만들 수 있습니다. 정말 간단하네요!
그럼 이제 Section Snapshot을 사용해서 계층 구조를 만들 수 있다는 것을 알았는데, 가끔은 계층 구조에서 일부만 필요할 때도 있겠죠.
그럴 때 위 코드와 같이 특정 계층의 모든 하위 목록을 가지고 올 수도 있다고 합니다.
그럼 다음은 Expanding 상태에 대해 살펴보겠습니다. Expanding 상태도 Section Snapshot 상태의 일부로 관리되는데, 간단하게 말해서 하위 데이터가 보일지 말지를 결정할 수 있는 기능입니다.
표시할 Snapshot을 만들 때 해당 항목의 상위 Expanding 상태를 설정해서 하위 콘텐츠가 표시될지 말지를 결정할 수 있습니다. Snapshot을 검색해서 하위 콘텐츠가 보이는지 안 보이는 지도 확인할 수 있다고 하네요. 이렇게 Section Snapshot의 Expanding 상태를 변경하면 Diffable Data Source의 apply를 호출할 때까지는 적용되지 않는다고 합니다.
Expansion 상태를 정리해보면, 아까 알아본 대로 Section Snapshot이 이를 관리하며 표시할 Snapshot을 만들 때 상위 계층의 Expansion 상태를 설정해서 하위 계층이 처음에 표시될지 말지 결정할 수 있다고 했습니다. 또한 Snapshot을 쿼리 해서 Expansion 상태를 확인할 수도 있고 Diffable Data Source의 apply를 호출하기 전까지는 변경사항이 적용되지 않았습니다.
그럼 방금 알아본 기능을 위한 API를 살펴보겠습니다. 위 코드를 보면 Diffable Data Source에 "SectionSnapshotHandlers"라는 새로운 타입이 있는 것을 알 수 있습니다. 새로운 타입은 Item에 대한 제네릭이고 5개의 optional 클로저를 가지고 있는 구조체네요.
방금 알아본 Expansion 상태에 대한 요구사항을 처리하기 위한 다양한 handler가 구현되어있습니다. 여기서 snapshotForExpandingParent를 사용하면 크기가 큰 콘텐츠에 대한 lazy loading도 가능하다고 합니다. 이는 어떤 콘텐츠를 가지고 올 때 자원이 많이 든다면 초기 Section Snapshot에 로드된 콘텐츠의 양을 최소화하는데 유용하게 사용할 수 있다고 합니다. 즉 계층이 깊게 있다면 모든 자식 콘텐츠를 가지고 오지 않고 필요한 만큼만 로드해서 사용하겠다는 의미로 보입니다.
Reordering Support
Diffable Data Source의 새로운 기능 중 하나는 CollectionView의 데이터를 고유한 item identifier로 모델링하는 기능입니다.
이렇게 고유한 item identifier를 사용하면 프레임워크가 사용자 상호작용을 기반으로 앱을 대신해서 reorder 작업을 커밋할 수 있습니다. 하지만 이것만으로는 충분하지 않고, 앱에 사용자가 reorder 작업을 발생했음을 알려야지 최종 source of truth인 백업 저장소에 새로운 순서로 된 UI를 유지할 수 있다고 합니다.
따라서 reordering을 지원하기 위해 Diffable Data Source에는 ReorderingHandlers라는 새로운 타입이 정의되었습니다. 얘도 3개의 optional 클로저를 갖는 구조체로, 이를 활용해서 reordering을 활성화하려면 먼저 canReorderItem 클로저를 제공해야 한다고 합니다.
canReorderItem은 사용자가 reorder 작업을 시작하려고 할 때 호출되며, true를 반환하면 작업을 시작할 수 있습니다. 작업이 완료되면 didReorder가 호출되어 앱이 새로운 상태를 앱의 source of truth에 커밋할 수 있도록 해줍니다. 즉 reordering 기능을 사용하기 위해선 canReorderItem, didReorder 클로저를 모두 제공해야 한다는 것을 의미합니다.
여기서 didReorder 클로저는 새로운 타입인 NSDiffableDataSourceTransaction을 전달하는데 얘가 뭔지도 살펴보겠습니다.
트랜잭션은 Diffable Data Source에 대해 수행되는 업데이트를 추론하는데 필요한 모든 정보를 제공합니다.
먼저 NSDiffableDataSourceTransction을 살펴보면, 네 개의 기본 정보를 제공하네요. 먼저 업데이트되기 전의 Data Source 상태인 initialSnapshot이 있네요. 그리고 업데이트 후 상태인 finalSnapshot이 있습니다. 이 Snapshot의 item identifier를 사용해서 앱의 소스에 커밋해야 하는 새로운 순서를 결정할 수 있다고 합니다.
그리고 swift 표준 라이브러리에서 제공하는 CollectionDifference 타입인 differance가 있습니다. 앱에서 source of truth에 대한 Array와 같은 데이터 타입이 있는 경우 CollectionDifference를 해당 데이터 타입에 직접 적용할 수 있다고 하는데.. 뭔 말인지 이해가 잘 안 되네요. ㅠ
마지막으로 현재 ordering 작업과 관련된 모든 섹션에 대한 섹션별 세부 정보를 제공하는 sectionTransactions가 있습니다. 그럼 다음으로는 NSDiffableDataSourceSectionTransaction도 알아봅시다.
NSDiffableDataSourceSectionTransaction도 비슷한데요, 얘네는 하나의 섹션에 대한 트랜잭션만 제공됩니다. 그래서 이를 구분하기 위한 sectionIdentifier가 있네요. 그 외엔 똑같습니다. 물론 하나의 섹션에 대한 트랜잭션이니 sectionTransactions와 같은 정보는 필요 없어요.
예제를 살펴보면, 위 코드의 backingStore는 하나의 섹션이 있는 CollectionView에 대한 정보를 제공하는 [Item]입니다. 트랜잭션과 함께 제공된 CollectionDifference를 사용해서 새로운 백업 저장소를 만들고 source of truth를 직접 업데이트한다고 합니다.
이렇게 영상은 끝이 납니다.
일단 이번 영상은 iOS 14에서 Diffable Data Source에 추가된 기능인 Section Snapshot과 Reordering Taansactions를 알아보는 영상이었네요.. Diffable Data Source의 기본 기능을 공부하고 싶었는데, 추가 기능부터 알게 된 느낌입니다. 🥲
데이터를 계층 구조로 처리하는 기능이나 섹션별로 Snapshot을 다루는 기능, Reordering 기능들이 모두 유용해 보이긴 하는데, 직접 사용을 해봐야 확실히 알 수 있겠네요.
공부할게 정말 많네요 🥲
감사합니다.