<h1><center> CollectionView - FlowLayout vs CompositionalLayout </center></h1>
###### title: `CollectionView - FlowLayout vs CompositionalLayout`
###### tags: `💻 TIL`, `CollectionView`, `UICollectionViewFlowLayout`, `CompositionalLayout`
###### date: `2023-11-15T10:39:33.284Z`
> [color=#724cd1][name=데릭]
> [Apple - UICollectionViewFlowLayout
](https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout)
> [Apple - UICollectionViewCompositionalLayout](https://developer.apple.com/documentation/uikit/uicollectionviewcompositionallayout)
## 개요
> UICollectionViewFlowLayout과 CompositionalLayout이 무엇인지, 차이점은 어떤게 있는지 학습해보자.
> 둘 다 UICollectionViewLayout을 상속한다.
## UICollectionViewFlowLayout
> 각 Section에 대한 Optional Header, Footer 뷰가 있는 Grid로 Item을 구성하는 레이아웃 객체이다.
컬렉션 뷰의 Item은 스크롤 방향에 따라 한 Column(스크롤 방향에 따라)에서 다음 Column으로 흐르며, 각 Column에는 가능한 많은 셀이 포함된다.
- 셀의 크기는 같을 수도 있고 다를 수도 있다. 설정에 따라 다르다.
Flow Layout은 컬렉션 뷰의 Delegate 객체와 함께 작동하여 각 Section과 Grid의 items, Header, Footer 크기를 결정한다.
- Delegate를 사용하면 레이아웃을 동적으로 조절할 수 있다.
또한, 한 방향(vertical or horizontal)에서 고정 거리를 가지고(Width or Height가 고정되는것) 스크롤 가능한 거리를 측정하여 Content를 배치한다.
예를 들어, Vertical 스크롤 그리드에서 그리드의 콘텐츠의 width는 컬렉션 뷰의 width로 제한된다. 그러나, 콘텐츠 의 Height는 그리드의 Section, item 수에 맞춰 동적으로 조절된다.
- Default: Vetical Scrolling
- `scrollDirection`프로퍼티를 사용하여 스크롤 방향을 구성할 수 있다.
그리고 각 섹션에 고유한 Custom Header와 Footer가 있을 때, 뷰의 Header나 Footer를 구성하려면 Size를 0이 아닌 값으로 구성해야한다.
```swift
let layout = UICollectionViewFlowLayout()
let sectionSpacing: CGFloat = 20
let itemSpacing: CGFloat = 8
// 수직 스크롤이라는 가정 하에, rowCount는 몇개의 행을 사용할지를 저장한 변수
let width: CGFloat = UIScreen.main.bounds.width - (itemSpacing * (rowCount-1)) - (sectionSpacing * 2)
let itemWidth: CGFloat = width / rowCount
// 각 item의 크기 설정 (아래 코드는 정사각형을 그린다는 가정)
layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
// 스크롤 방향 설정
layout.scrollDirection = .vertical
// Section간 간격 설정
layout.sectionInset = UIEdgeInsets(top: sectionSpacing, left: sectionSpacing, bottom: sectionSpacing, right: sectionSpacing)
// item간 간격 설정
layout.minimumLineSpacing = itemSpacing // 최소 줄간 간격 (수직 간격)
layout.minimumInteritemSpacing = itemSpacing // 최소 행간 간격 (수평 간격)
collectionView.collectionViewLayout = layout // collectionView에 설정한 Layout 인스턴스를 할당
```
## UICollectionViewCompositionalLayout
> 적응력이 뛰어나고 유연한 시각적 배열로 Item을 결합할 수 있는 레이아웃 객체이다. <br>
> Layout을 별도의 시각적 Grouping으로 나누는 하나 이상의 Section으로 구성된다.
> 각 섹션은 표시하려는 데이터의 가작 단은 단위인 개별 Item Group으로 구성된다.
> 그룹은 Item을 Horizontal Row, Vertical Column 또는 Custom 배열로 배치할 수 있다.

> UICollectionViewCompositionalLayout의 Layout 구성
## 둘의 차이점
||UICollectionViewFlowLayout|UICollectionViewCompositionalLayout|
|---------------------|--------|---------|
| **구조적 차이** | |구조를 더 추상화하고, 그룹화된 섹션과 아이템의 레이아웃을 정의하는 데에 중점을 둔다.|
| **동적 레이아웃** ||런타임에서 동적으로 레이아웃을 조절할 수 있는 기능을 제공한다. 조금 더 유연하게 대응할 수 있다. |
| **API 설계** | |함수형 프로그래밍 스타일을 기반으로 한 API를 사용하여 레이아웃을 정의한다. |
| **코드의 간결성** || 선언적으로 정의할 수 있기 때문에 코드가 더 간결하고 읽기 쉬워지는 경향이 있다.|
**선언적 정의 예시**
```swift
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .vertical
flowLayout.itemSize = CGSize(width: 100, height: 100)
flowLayout.minimumInteritemSpacing = 10
flowLayout.minimumLineSpacing = 10
let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: 300, height: 300), collectionViewLayout: flowLayout)
```
> UICollectionViewFlowLayout
```swift
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.25), heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalWidth(0.25))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
```
> UICollectionViewCompositionalLayout