NSCollectionLayoutDimension을 사용한 첫 UICollectionViewCompositionalLayout 구현하기

작성일 :

NSCollectionLayoutDimension을 사용한 첫 UICollectionViewCompositionalLayout 구현하기

UICollectionView는 iOS 개발에서 굉장히 강력한 도구입니다. UICollectionView를 사용하면 화면에 데이터를 다양한 방식으로 배치할 수 있습니다. Swift에서는 컴포지셔널 레이아웃을 사용하여 복잡한 레이아웃을 간단하게 구축할 수 있습니다. 이 글에서는 NSCollectionLayoutDimension을 사용하여 첫 번째 UICollectionViewCompositionalLayout을 구현하는 방법을 설명하겠습니다.

컴포지셔널 레이아웃의 기본 개념

컴포지셔널 레이아웃은 iOS 13에서 소개된 기능으로, 새로운 방식으로 컬렉션뷰의 레이아웃을 구성할 수 있게 해줍니다. 이 레이아웃 시스템은 레이아웃을 작은 단위인 섹션으로 나누고, 각 섹션은 항목들로 구성됩니다. 각 항목은 상응하는 레이아웃 크기와 위치를 지정할 수 있습니다.

컴포지셔널 레이아웃의 주요 요소는 다음과 같습니다.

  • 아이템: 기본 구성 요소로, 셀에 해당합니다.
  • 그룹: 아이템들을 포함하는 컨테이너입니다.
  • 섹션: 그룹들을 포함하는 컨테이너입니다.
  • 레이아웃: 섹션들을 배열하여 전체 컴포지셔널 레이아웃을 정의합니다.

NSCollectionLayoutDimension 소개 및 사용 예시

NSCollectionLayoutDimension은 아이템, 그룹 또는 섹션의 크기를 정의하는 데 사용됩니다. 이 클래스는 항목의 너비와 높이를 지정하는 다양한 방법을 제공합니다. 주요 메서드는 다음과 같습니다.

  • absolute(_:): 절대 값을 사용하여 크기를 지정합니다.
  • fractionalWidth(_:): 부모의 너비에 대한 비율로 크기를 지정합니다.
  • fractionalHeight(_:): 부모의 높이에 대한 비율로 크기를 지정합니다.
  • estimated(_:): 추정 크기를 사용하여 지정합니다.

절대 크기 사용 예시

절대 크기를 사용하면 항목의 크기를 픽셀 단위로 고정합니다. 예를 들어, 아이템의 너비와 높이를 각각 100포인트로 설정할 수 있습니다.

swift
let itemSize = NSCollectionLayoutSize(widthDimension: .absolute(100), heightDimension: .absolute(100))
let item = NSCollectionLayoutItem(layoutSize: itemSize)

비율 크기 사용 예시

부모의 크기에 대한 비율을 사용하여 크기를 지정할 수도 있습니다. 예를 들어, 아이템의 너비를 부모의 너비의 50%로 설정할 수 있습니다.

swift
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)

첫 번재 UICollectionViewCompositionalLayout 구현

이제 앞서 설명한 개념들을 조합하여 첫 번째 UICollectionViewCompositionalLayout을 구현해 보겠습니다. 이 예제에서는 두 개의 다른 섹션이 있으며, 첫 번째 섹션에는 가로 스크롤이 가능한 큰 이미지 아이템이 있고, 두 번째 섹션에는 세 개의 작은 이미지 아이템이 세로로 배치됩니다.

기본 설정

우리는 먼저 기본 설정으로 UICollectionView를 생성하고 레이아웃을 정의하도록 하겠습니다.

swift
import UIKit

class ViewController: UIViewController {
    var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureHierarchy()
    }
    
    private func configureHierarchy() {
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
        collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(collectionView)
    }
    
    private func createLayout() -> UICollectionViewCompositionalLayout {
        let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
            return self.createSection(for: sectionIndex)
        }
        return layout
    }

    private func createSection(for sectionIndex: Int) -> NSCollectionLayoutSection {
        // 섹션을 정의합니다.
        if sectionIndex == 0 {
            return createFirstSection()
        } else {
            return createSecondSection()
        }
    }
}

섹션 구성

첫 번째 섹션은 가로 스크롤이 가능한 큰 이미지 아이템들을 포함합니다. 각 아이템의 너비는 부모의 전체 너비이고 높이는 200포인트로 설정합니다.

swift
private func createFirstSection() -> NSCollectionLayoutSection {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(200))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(200))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    
    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .continuous
    return section
}

두 번째 섹션은 세 개의 세로로 배치된 작은 이미지 아이템들을 포함합니다. 각각의 아이템은 부모의 너비의 1/3로 설정합니다.

swift
private func createSecondSection() -> NSCollectionLayoutSection {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.3), heightDimension: .fractionalHeight(1.0))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)

    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(100))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    
    let section = NSCollectionLayoutSection(group: group)
    return section
}

이제 createSection(for:) 메서드에서 섹션들을 반환합니다.

swift
private func createSection(for sectionIndex: Int) -> NSCollectionLayoutSection {
    if sectionIndex == 0 {
        return createFirstSection()
    } else {
        return createSecondSection()
    }
}

이로써, 우리는 첫 번째 UICollectionViewCompositionalLayout을 구현했습니다. 이제 이 레이아웃을 통해 컬렉션뷰가 다양한 데이터와 스크롤 동작을 가진 섹션들로 채워질 수 있습니다.

결론

이 글에서는 NSCollectionLayoutDimension을 사용하여 첫 번째 UICollectionViewCompositionalLayout을 구현하는 방법을 다루었습니다. 컴포지셔널 레이아웃을 사용하면 복잡한 레이아웃도 손쉽게 정의할 수 있으며, 다양한 스크롤 동작과 항목 배치를 구현할 수 있습니다. iOS 개발에서 컬렉션뷰의 유연성을 최대한 활용하고 싶다면, 컴포지셔널 레이아웃은 반드시 익혀야 할 도구입니다.