View

hyun·2025년 5월 22일
2

iOS

목록 보기
3/54

 UICollectionView vs UITableView

UICollectionView

앱 화면에 여러 개의 상자를 가지런히 보여주는 도구
이 상자 안에는 사진, 글자, 버튼 등 네가 원하는 걸 넣을 수 있음

ex)

사진 앨범처럼 여러 장의 사진을 줄 맞춰서 보여줄 때

카드 뉴스처럼 옆으로 넘기는 카드들을 만들고 싶을 때

UITableView와의 차이점

비교 항목UITableView (테이블뷰)UICollectionView (컬렉션뷰)
모양세로로 한 줄씩 내려가는 리스트가로, 세로, 격자 등 다양하게 배치 가능
쓰는 곳채팅, 뉴스 목록 등사진첩, 카드 슬라이드, 게임 캐릭터 선택 화면 등

요약 )

테이블 뷰는 줄 세우기만 잘함

컬렉션 뷰는 배줄도 세우고, 칸도 나누고, 옆으로 넘기기도 잘함

컬렉션 뷰 만드는 법

컬렉션 뷰를 만들기 위해 필요한 것들

1️⃣ 어떤 데이터를 보여줄지 정하기 (데이터 소스)

ex) 사진 10장을 보여줘, 그림 카드 5개 있어요 이런 거 알려줘야 함

몇 개의 아이템(상자)을 보여줄지

각각 상자 안에 뭐 넣을지 정해주는 것

2️⃣ 셀 등록하기 (상자 준비하기)

ex) 이 상자는 사진을 넣을 상자임. 하고 미리 만들어두는 것

이걸 해야 앱이 이 상자를 써야 되는구나 하고 알아차릴 수 있음

3️⃣ 어떻게 배치할지 정하기 (레이아웃)

ex) 상자를 10/10 크기로 만들고, 옆으로 10씩 띄워주셈 같은 걸 정하는 것

레이아웃은 상자들을 어떻게 정렬할지 알려주는 설계도? 같은 역할

UICollectionView는 언제 쓸까

사진첩 앱

가로로 쭉 이어진 아이템

드래그해서 정렬 바꾸는 화면

UICollectionView 안에 줄지어 있는 작은 상자
(직접 디자인 가능)

테이블 뷰와 컬렉션 뷰 비교 요약

항목UITableViewUICollectionView
기본 방향세로 리스트그리드, 가로/세로/자유 레이아웃
셀 배치섹션당 1열여러 열, 자유로운 배치
셀 크기delegate로 조절 가능자유롭게 조정 가능
커스터마이징단순한 구조매우 유연, 복잡한 레이아웃 가능
레이아웃 클래스기본 고정UICollectionViewLayout으로 직접 정의
예시 채팅, 뉴스피드, 연락처사진첩, 카드 UI, 쇼핑몰 상품 목록

언제 어떤 걸 써야 할까?

UITableView 사용 추천

세로 리스트
단순 데이터
채팅, 연락처, 뉴스 리스트

UICollectionView 사용 추천

그리드 || 가로/세로 조합 레이아웃
복잡한 셀 배치
사진 앨범, 넷플릭스 UI, 카드 스타일

UICollectionView 기본 사용법

1. 셀 클래스 만들기

class MyCollectionViewCell: UICollectionViewCell {
    let titleLabel = UILabel()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.textAlignment = .center
        contentView.addSubview(titleLabel)
        NSLayoutConstraint.activate([
            titleLabel.centerXAnchor.constraint(equalTo: contentView.centerXAnchor),
            titleLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor)
        ])
        contentView.backgroundColor = .systemGray5
        contentView.layer.cornerRadius = 8
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

2. 컬렉션 뷰 만들기 (뷰 컨트롤러 내)

class MyCollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    var items = ["하나", "둘", "셋", "넷", "다섯"]
    var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        // 1. 레이아웃 정의
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSize(width: 100, height: 100)
        layout.minimumLineSpacing = 16
        layout.minimumInteritemSpacing = 16
        layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

        // 2. 컬렉션 뷰 생성
        collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
        collectionView.backgroundColor = .white
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
        view.addSubview(collectionView)
    }

    // 3. 셀 개수 정의
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }

    // 4. 셀 구성
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? MyCollectionViewCell else {
            return UICollectionViewCell()
        }
        cell.titleLabel.text = items[indexPath.item]
        return cell
    }
}

핵심 정리

용어설명
UICollectionViewCell각각의 셀 (아이템)
UICollectionViewFlowLayout셀 배치 방식 결정
register셀 클래스 등록
dequeueReusableCell셀 재사용
contentView셀 내부 뷰 추가 위치

 컬렉션 뷰 레이아웃 설정과 셀 크기 조절 방법

핵심 정리 요약

항목기능
UICollectionViewFlowLayout기본 레이아웃 구성 클래스
itemSize셀 크기 고정 설정
minimumLineSpacing / minimumInteritemSpacing셀 간격 설정
sectionInset섹션 주변 여백
scrollDirection스크롤 방향 (세로/가로) 설정
UICollectionViewDelegateFlowLayout셀 크기를 indexPath마다 동적으로 지정 가능
sizeForItemAt셀 크기 동적 계산 구현 메서드

이런 상황

상황적용 방법
모든 셀 크기가 동일해야 할 때layout.itemSize 사용
셀 크기를 내용에 따라 다르게 하고 싶을 때sizeForItemAt에서 동적 계산
반응형 셀 배치를 원할 때 (2~3열)컬렉션 뷰 너비 기준으로 셀 너비 계산
텍스트 길이에 맞춘 셀 크기NSString.size(withAttributes:) 사용
커스텀 셀의 내부 뷰 크기에 따라 자동 크기preferredLayoutAttributesFitting(_:) 오버라이드

 Swift UICollectionView & UIScrollView 정리

UICollectionViewCell 커스텀 요약

단계내용
1️⃣ 셀 클래스 생성UICollectionViewCell을 상속받고 UIImageView, UILabel 같은 UI 요소 추가
2️⃣ UI 설정setupUI() 메서드에서 addSubview + NSLayoutConstraint로 오토레이아웃 설정
3️⃣ 셀 등록collectionView.register(CustomCell.self, forCellWithReuseIdentifier: "CustomCell")
4️⃣ 데이터 바인딩cellForItemAt에서 imageView.image와 titleLabel.text 설정
5️⃣ 모델 구조체struct Item { let title: String; let imageName: String } 등으로 데이터 구성

contentMode = .scaleAspectFill, layer.cornerRadius, shadow 등으로 디자인 개선 가능

셀 레이아웃은 꼭 오토레이아웃으로 설정해야 스크롤 성능 저하 없이 잘 작동함

UIScrollView 구성 요약

단계내용
1️⃣ 뷰 추가UIScrollView > UIView 구조로 구성 (스크롤뷰 안에 콘텐츠 뷰)
2️⃣ 오토레이아웃scrollView는 view에, contentView는 scrollView.contentLayoutGuide에 맞춤
3️⃣ 콘텐츠 너비 고정contentView.widthAnchor = scrollView.frameLayoutGuide.widthAnchor
4️⃣ 요소 추가contentView에 원하는 UI 요소 추가 후 제약 설정
5️⃣ 높이 중요콘텐츠 높이가 scrollView보다 커야 실제 스크롤 작동함

주의

UIScrollView 안에서 스크롤이 안 되는 경우는 대부분 오토레이아웃이 빠졌거나,
콘텐츠 높이가 부족한 경우

 AutoLayout을 활용한 스크롤 가능한 화면 만들기

1️⃣ 기본 구조

view (UIViewController의 기본 뷰)
└── scrollView (UIScrollView)
    └── contentView (UIView)
        └── [여기에 여러 UI 요소 배치]

화면보다 큰 콘텐츠가 있을 경우 자동 스크롤이 가능하게 됨

2️⃣ 전체 코드 흐름 예시

class ScrollExampleViewController: UIViewController {

    let scrollView = UIScrollView()
    let contentView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        setupScrollView()
        setupContent()
        setupLayout()
    }

    private func setupScrollView() {
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(scrollView)

        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
    }

    private func setupContent() {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(contentView)

        NSLayoutConstraint.activate([
            contentView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
            contentView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),

            // 수평 스크롤 방지
            contentView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
        ])
    }

    private func setupLayout() {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.numberOfLines = 0
        label.text = Array(repeating: "스크롤 가능한 텍스트입니다.", count: 50).joined(separator: "\n")
        contentView.addSubview(label)

        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -20)
        ])
    }
}

오토레이아웃 설정 핵심

대상제약 조건 설명
scrollView → view화면에 꽉 차도록 top, leading, trailing, bottom 제약
contentView → scrollView.contentLayoutGuide콘텐츠 전체 높이 기준으로 스크롤 영역 설정
contentView.widthAnchor → scrollView.frameLayoutGuide.widthAnchor수평 스크롤 방지 (세로 스크롤만 가능)
내부 요소 → contentView오토레이아웃으로 콘텐츠 배치 (예: UILabel 등)

다짐을 남기는 앱을 만들기 위해 Figma를 이용하여 디자인을 하였음 !

거의 60% 완료하였음... 근데 구현하는 게 생각보다 빡세서 좀 더 해봐야할 것 같다!

0개의 댓글