아키텍처 : MVVM
ViewController는 UI/이벤트 처리, ViewModel은 API 호출/데이터 가공/검색 로직 담당
UICollectionViewCompositionalLayout으로
리스트 : 한 줄에 포스터 3개씩 연속 스크롤
검색 : 3열 그리드
DiffableDataSource 패턴 적용
SnapKit : 오토레이아웃 제약을 선언형으로 간결하게
Then : 뷰 초기화 이후 속성 설정을 클로저로 정리
Kingfisher로 URL 기반 포스터 비동기 다운로드 및 캐싱
번들 MP4를 AVPlayer로 AVPlayerLayer에 삽입, 재생 완료 후 로그인 화면으로 전환
관심사의 분리로 ViewController가 깔끔해지고 테스트 가능한 ViewModel 구현
Compositional Layout 덕분에 복잡한 섹션 레이아웃을 선언적으로 정의
Kingfisher 도입해서 이미지 로딩 코드 대폭 단순화하였고 스크롤 퍼포먼스 안정화 시킴
AVPlayer 기반 스플래시로 외부 라이브러리 의존 최소화, 영상 재생
레이아웃 디테일 튜닝
Safe Area/헤더 타이틀 정렬, 기기별 마진 계산
데이터 매핑 로직
섹션별 배열 분기 및 역순 처리 시 인덱스 오류 방지
검색 필터링 스레드 문제
textDidChange 콜백에서 메인 스레드 동기화 누락 시 UI 깜빡임
키보드 충돌 처리
컬렉션뷰 바텀 제약과 키보드 나타남 시 레이아웃 깨짐
네트워크 에러 처리 & 로딩 상태 UI
스켈레톤 뷰나 인디케이터 추가
무한 스크롤·프리페칭
검색/리스트 페이징 지원, UICollectionViewDataSourcePrefetching 적용
ViewModel 로직(검색 필터링, API 에러 케이스) 케이스별 검증
공통 컴포넌트화
셀, 레이아웃 정의, 스타일 가이드 모듈화로 재사용성 향상
ViewModel에서 데이터 로드
TMDB API로 popular·now_playing·upcoming 영화를 비동기 불러와 state에 저장하고, 변경 시 클로저로 컬렉션뷰 갱신
컴포지셔널 레이아웃 구성
컬렉션뷰를 가로 스크롤 섹션으로 설정해, 한 그룹에 포스터 3개씩 배치하고 간격·인셋을 지정
셀에 포스터 표시
MoviePosterCell의 버튼에 Kingfisher로 이미지를 로드하고 tag·accessibilityIdentifier로 섹션·인덱스를 설정
셀 탭 시 상세 이동
버튼 액션 또는 셀 선택으로 섹션·인덱스를 판별해 해당 MovieResults를 MovieDetailViewController에 전달하고 푸시
fetchAllData()로 TMDB 데이터를 불러와, onDataUpdated에서 reloadData()와 updateEmptyState()를 호출해 컬렉션뷰 갱신.minimal 스타일의 UISearchBar로 입력을 감지해 updateSearch(_:)로 state.searchResults를 실시간 필터링searchResults.isEmpty면 "검색 결과 없음" 레이블을 backgroundView에, 아니면 레이블 숨김MovieResults를 MovieDetailViewController에 전달해 pushViewController로 이동