본문 바로가기
감정일기(가칭)

커스텀 캘린더 만들기 구조 설계

by 밤새는 탐험가89 2025. 11. 10.
728x90
SMALL

🔍 현재 구조 복기

CustomCalendarViewController
 ├── pagerCollectionView (수평 페이징, [이전/현재/다음] 월)
 │     └── MonthCollectionCell
 │           └── collectionView (7열 날짜 그리드)
 │                 └── CalendarDayCell

 

 

- pagerCollectionView → 월 단위 스크롤

- MonthCollectionCell → 한 달의 날짜 그리드

- CalendarDayCell → 각 날짜 표시

 

🧩 MonthCollectionCell을 없애면 생기는 변화

MonthCollectionCell을 제거하면 아래처럼 단순해져요.

CustomCalendarViewController
 └── collectionView (수평 페이징 + 날짜 셀)
       └── CalendarDayCell

 

이제 CalendarViewModel.days(in:)으로
그 달의 날짜 배열(예: 35개)을 만들어
바로 cellForItemAt에서 뿌릴 수 있습니다.

 

단, 문제는 "월별 페이징"을 구현하려면 컬렉션뷰가 섹션 단위로 월을 나눠야 한다는 점이에요.

 

반대로,
“월 단위 페이징”을 유지하면서,
코드를 읽기 쉽게만 정리하고 싶다면
MonthCollectionCell을 남겨두는 게 나쁘지 않습니다.

 

이유는 👇

1. 달력은 “이중 컬렉션 구조”가 오히려 명확한 책임 분리를 제공합니다.

- 상위 컬렉션뷰: 월 단위 페이징

- 하위 컬렉션뷰: 날짜 그리드

 

2. MonthCollectionCell이 있으면
각 월의 뷰를 독립적으로 reload/reuse 할 수 있음


(성능상 유리, 테스트/유지보수도 편함)

즉, 지금 구조는 조금 복잡해 보이지만
실제로는 “확장성 높은 패턴”이에요.

 

✅ 전체 구조 다시 도식화하면

CustomCalendarViewController
 └── pagerCollectionView  ← [1월, 2월, 3월] 월 단위 수평 스크롤
       └── MonthCollectionCell (각 월 하나)
             └── collectionView ← 7열 그리드 (날짜 배치)
                   └── CalendarDayCell ← 날짜 표시 (예: 1, 2, 3 …)

 

🧩 각 역할 설명

레벨 클래스 역할 주 데이터
CustomCalendarViewController 전체 달력의 “페이지 관리자” [1월, 2월, 3월] (viewModel.months)
MonthCollectionCell 한 달짜리 달력 그리드 (7열 × 5~6행) [Date?] (해당 달의 모든 날짜 + 공백)
CalendarDayCell 하루를 그리는 셀 (텍스트, 감정 아이콘 등) Date? (1일~31일 중 하루)

 

🔁 데이터 흐름 예시

예를 들어,
CustomCalendarViewController가 2025년 2월을 중앙에 띄웠다고 해볼게요.

 

1️⃣ ViewModel에서 3개월 정보 계산

viewModel.months = [2025-01-01, 2025-02-01, 2025-03-01]

 

2️⃣ pagerCollectionView → 각 MonthCollectionCell 생성

cell.configure(month: 2025-02-01, viewModel: viewModel)

 

3️⃣ MonthCollectionCell → 그 달의 날짜 배열 계산

days = viewModel.days(in: 2025-02-01)
// => [nil, nil, 1일, 2일, ..., 29일]

 

4️⃣ 내부 collectionView → CalendarDayCell 하나씩 채움

dateLabel.text = "1"
dateLabel.text = "2"
...

 

🔄 사용자가 스크롤할 때

pagerCollectionView에서 왼쪽/오른쪽으로 스와이프
→ ViewModel이 moveMonth() 호출
→ [이전, 현재, 다음] 배열 갱신
→ reload 후 가운데 페이지로 복귀

이 패턴 덕분에 무한 월 스크롤이 자연스럽게 됩니다.


🧠 핵심 포인트 요약

개념 설명
pagerCollectionView 월 단위 스크롤 담당 (수평 페이징)
MonthCollectionCell 한 달의 “그리드(달력)” 표현 담당
CalendarDayCell 한 칸(하루)의 시각적 표시 담당
viewModel.days(in:) 특정 달의 날짜 + 앞쪽 nil 공백 생성
장점 역할 명확, 각 Month 재사용 가능, 확장성 높음

 

728x90
LIST