> For the complete documentation index, see [llms.txt](https://sois-organization.gitbook.io/today-i-learned/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sois-organization.gitbook.io/today-i-learned/wwdc/uikit/wwdc2019-advances-in-collectionview-layout.md).

# \[WWDC2019] Advances in CollectionView Layout

#### CollectionView Layout의 발전 목차

1. **CollectionView의 현재 기술** (current state of the art)
2. (iOS, tvOS, MacOS) **새로운 접근 방식** (a new approach)
3. **Demo**
4. **고급 기능** (advanced layouts)

***

### 1. CollectionView의 현재 기술 (current state of the art)

#### UICollectionViewFlowLayout

1. CollectionViewLayout
   * Layout을 정의하기 위해 두 가지 역할을 가진 클래스로 추상화되어있다.
     * rendering을 하는 class
     * collectionView Layout이 어디로 가는지?에 대해 책임을 지는 class
     * CollectionView Layout은 추상화되어있기 때문에 사용하려면 항상 Subclassing을 해야한다.

       이것을 Concrete type으로 정의한 것이 iOS 6에서 발표했던 CollectionView Flow Layout이다.
2. CollectionViewFlowLayout
   * line based layout system이었기 때문에, iOS6을 사용했던 환경에서 매우 유용하게 사용됐다.
     * (2018 WWDC 영상 참고) 단순히 Line들을 배치하고, 축을 기반으로 배치해서 Layout을 구성할 수 있다.
     * 매우 간단하고, 추론이 쉬우며, 빠르다는 장점이 있다.
     * 하지만 요즘에 이종화되는 기기와, 다양한 custom layout이 나오면서 UI가 매우 복잡해졌다.

***

* 복잡해진 UI로 인해 발생하는 문제점을 살펴보자.

  ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/d74f14bc-8851-4ea5-b86d-88e5c0523949/Untitled.png)
* AppStore의 메인화면을 구성하기 위해 우리는 다양한 컴포넌트를 고민할 것이다.
  * 다양한 모양의 Cell이 존재하기 때문에, CollectionView를 선택했다고 가정하자.

    이때, “Flow”를 표현할 수 있을지 고민하기 시작하자마자 CollectionView 사용을 포기하게 된다. (이유는 몰까)
* Custom Layout을 설계할 때 발생할 수 있는 문제점

  * Boilerplate code
  * Performance considerations
  * Supplementary and decoration view challenges
    * CollectionView에서 관리할 수 있는 View, DecorationView는 CustomLayout에서 까다롭게 작용한다.
  * Self-sizing challenges

  ⇒ 이 문제들을 해결하기 위해 Flow와 동일한 Concrete class인 새로운 플랫폼을 도입했으며, 이것이 바로 Compositional Layout이다.

***

### 2. **새로운 접근 방식** (a new approach)

#### Compositional Layout의 개념

* Compositional Layout의 중심 개념 3가지
  1. Composable

     간단한 것을 이용해서 복잡한 것을 만든다.
  2. Flexible

     유연하게 설계되어, 어떤 레이아웃이든 작성할 수 있다.
  3. Fast

     자체 최적화를 수행하여 빠르다.
* Compositional Layout은 Layout을 설명하거나, 정의하는 선언형 API이다.

#### Compositional Layout의 활용

* Composing small layout groups together

  작은 레이아웃을 만들고, 이들을 조합해서 더 큰 레이아웃을 구성한다.
* Layout groups are line-based

  FlowLayout의 장점을 이어가기 위해 line based에 따라 레이아웃을 그릴 수 있다. (굉장히 많은 UI)

  작은 레이아웃 그룹을 한 줄로 Item을 배치할 수 있다.
* composition instead of subclassing

  Subclassing을 하지 않아도 된다. (Concrete type)

  추론 가능한 레이아웃으로 구성할 수 있기 때문에 매우 단순하다.

#### Compositional Layout Code 및 개념

* Core Concepts

  ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/dd8f7ba3-c04d-411d-b343-acceff60a6f7/Untitled.png)
* Type(유형)에 대해 자연스러운 Flow가 존재한다.
  * 5가지 유형이 존재한다. (Item, Group, Section, Layout)

    ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/9e8a8131-d82f-4344-8dfd-5c8ec61db257/Untitled.png)

#### Layout Types

1. Size

   * 모든 것들은 명백한 사이즈를 가지고 있다.
   * 사이즈를 쉽게 추론할 수 있는 방법 (각 Type이 얼마나 큰지 확인)

     Size = Width + Height dimension

   ```swift
   class NSCollectionLayoutSize {
   	init(widthDimension: NSCollectionLayoutDimension,
   			 heightDimension: NSCollectionLayoutDimension)
   }
   ```

   * NSCollectionLayoutDimension
     * 축과 무관한 방법으로, 폭과 높이, 차원에 대한 정보만을 이용해서 축의 크기를 설명한다.

       이때, 폭과 높이의 경우, NSCollectionLayoutDimension이라는 새로운 유형으로 정의한다.
     * NSCollectionLayoutDimension의 4가지 유형

       ```swift
       // 축의 크기를 나타내는 "축 독립적 방법"
       class NSCollectionLayoutDimension {
       	class func fractionalWidth(_ fractionalWidth: CGFloat) -> Self 
       	class func fractionalHeight(_ fractionalHeight: CGFloat) -> Self 
       	class func absolute(_ absoluteDimension: CGFloat) -> Self
       	class func estimated(_ estimatedDimension: CGFloat) -> Self
       }
       ```
     * 특정 Item의 width = Container 폭의 50%를 차지한다.

       ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/5768595e-34cf-476a-9605-6ed64e5693b8/Untitled.png)
     * Item의 Height = Container 폭의 30% 차지

       ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/a0b17d76-3643-444c-874e-c1753ca8dec1/Untitled.png)
     * 특정 종횡비를 갖도록 정의 (Container의 25%씩 aspect ratio)

       ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/efc51bb4-0d76-4e8e-a794-39272ed08436/Untitled.png)
     * 정확한 치수를 갖도록 정의 (point based value)

       ![스크린샷 2023-09-26 오후 12.43.37.png](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/3424070a-e439-42c3-abb2-37673f38e8d0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA_2023-09-26_%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE_12.43.37.png)
2. Item
   * 기존의 Cell의 개념과 동일

     ```swift
     class NSCollectionLayoutItem {
     	convenience init(layoutSize: NSCollectionLayoutSize)
     	var contentInsets: NSDirectionalEdgeInsets
     }
     ```
3. Group

   ![Untitled](https://prod-files-secure.s3.us-west-2.amazonaws.com/1a1e5f0d-7aa9-46a7-9110-f762ee7e5b77/896c488c-129c-475e-b569-abead6d76ebd/Untitled.png)
4. Section (`NScollectionLayoutSection`)
   * CollectionView의 단면을 기준으로 한 Layou의 정의
   * Section에 몇 개의 항목이 있는지에 대해 `DataSource`에 직접 매핑되는 개체
   * Initializer가 Group을 허용한다.

     ```swift
     class NSCollectionLayoutSection {
     	convenience init(layoutGroup: NSCollectionLayoutGroup)
     	var contentInsets: NSDirectionalEdgeInsets
     }
     ```
5. Layout

* 최상위 Layout class
* iOS, tvOS의 경우, UICollectionViewCompositionalLayout 사용
* MacOS의 경우, NSViewCompositionalLayout 사용
* 플랫폼과 상관 없이, 모든 정의가 동일하다.

  ```swift
  class UICollectionViewCompositionalLayout: UIcollectionViewLayout {
  	init(section: NSCollectionViewSection)
  	init(sectionProvider: @escaping SectionProvider)
  }
  ```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://sois-organization.gitbook.io/today-i-learned/wwdc/uikit/wwdc2019-advances-in-collectionview-layout.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
