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

✅ 주간 (일 ~ 토) 날짜를 요일 enum으로 매핑해주는 함수

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

✅ Weekday 변환이 실제로 쓰이는 곳: buildWeekDates()

주간 요약을 만들기 위해서는 해당 주(일요일~토요일)에 어떤 날짜가 있는지 알아야 해.

 

예를 들어
2025년 11월 20일 이 포함된 주라면:

일: 11/16  
월: 11/17  
화: 11/18  
수: 11/19  
목: 11/20  
금: 11/21  
토: 11/22

 

이렇게 요일 → 날짜 매핑이 필요해.

그 역할을 하는 것이 바로:

func buildWeekDates(from interval: DateInterval)

🔥 문제는 Calendar의 요일 값이 ‘정수’라는 점이다.

Apple Calendar는 요일을 숫자로 줘:

index 요일
1 Sunday
2 Monday
3 Tuesday
4 Wednesday
5 Thursday
6 Friday
7 Saturday

 

하지만 우리가 앱에서 사용하는 요일 타입은 enum:

enum Weekday: String, CaseIterable {
    case sun, mon, tue, wed, thu, fri, sat
}

 

즉,


Calendar → Int
우리 앱 → Weekday enum

 

👉 타입이 서로 안 맞음
👉 변환 과정 없이는 절대 정확한 매핑을 만들 수 없음


✨ 그래서 필요한 것이 바로 “weekdayIndex 초기화”

extension DiaryCoreDataManager.Weekday {
    init?(weekdayIndex: Int) {
        switch weekdayIndex {
        case 1: self = .sun
        case 2: self = .mon
        case 3: self = .tue
        case 4: self = .wed
        case 5: self = .thu
        case 6: self = .fri
        case 7: self = .sat
        default: return nil
        }
    }
}

 

이 코드는:

 

🟡 Calendar의 숫자 요일 → 앱의 enum 요일로 변환해주는 "다리"
🟡 잘못된 값이 들어오면 nil 처리 → crash 방지
🟡 어디서든 재사용 가능


📌 Weekday 변환이 buildWeekDates()에서 실제로 쓰이는 과정

buildWeekDates는 다음 일을 한다:

 

1. 주(weekInterval)의 시작일(일요일)부터 7일 반복

2. 매일 하루씩 증가

3. 요일 index(Int) 계산

4. 그 index를 enum Weekday로 변환 (바로 여기!)

5. 변환된 enum 요일에 해당 날짜를 저장


🔍 buildWeekDates 동작 코드 + 변환 적용

초보자도 바로 이해하도록 상세 주석을 추가해서 다시 정리하면:

/// 주간(일~토) 날짜를 요일 enum로 매핑해주는 함수
func buildWeekDates(from interval: DateInterval) -> [DiaryCoreDataManager.Weekday: Date] {
    let cal = calendar
    var dict: [DiaryCoreDataManager.Weekday: Date] = [:]

    // 이번 주의 7일 반복
    for offset in 0..<7 {
        // 매일 하루씩 증가한 날짜
        let day = cal.date(byAdding: .day, value: offset, to: interval.start)!

        // Calendar 방식(1~7) 요일 index
        let weekdayIndex = cal.component(.weekday, from: day)

        // 요일 index(Int) → Weekday enum 변환
        if let weekday = DiaryCoreDataManager.Weekday(weekdayIndex: weekdayIndex) {
            dict[weekday] = day
        }
    }

    return dict
}

📌 실행 흐름을 그림으로 이해해보자

주간 범위: 2025-11-16 ~ 2025-11-22

buildWeekDates는 다음을 수행함:

offset 날짜(day)  weekdayIndex(Int)  Enum 변환 결과 저장
0 11/16 1 .sun [.sun: 11/16]
1 11/17 2 .mon [.mon: 11/17]
2 11/18 3 .tue [.tue: 11/18]
3 11/19 4 .wed [.wed: 11/19]
4 11/20 5 .thu [.thu: 11/20]
5 11/21 6 .fri [.fri: 11/21]
6 11/22 7 .sat [.sat: 11/22]

 

[
  .sun: 11/16,
  .mon: 11/17,
  .tue: 11/18,
  .wed: 11/19,
  .thu: 11/20,
  .fri: 11/21,
  .sat: 11/22
]

 

이제 WeeklySummaryCell에서

 

1. 특정 날짜가 이번 달인지?

2. 이전 달 날짜인지?

3. 다음 달 날짜인지?

 

정확하게 판단할 수 있게 됨.


 🤔 궁금증...

- 왜 offset = 0인데 weekdayIndex = 1이 나오냐?

- 왜 extension에 init? 생성자로 만들었나? 그냥 var로 mapping 하면 안 되나?


✅ 1. offset은 “일수 증가”이고, weekdayIndex는 “요일 번호”이다 (전혀 다른 값)

먼저 코드 상황을 보자:

for offset in 0..<7 {
    let day = cal.date(byAdding: .day, value: offset, to: interval.start)!
    let weekdayIndex = cal.component(.weekday, from: day)
}

 

확실히 offset = 0이면 → interval.start 날짜 그대로지?

그런데 weekdayIndex는 offset과 전혀 상관없다.


📌 weekdayIndex란?

Calendar.component(.weekday, from:) 는 달력 기준의 요일 번호를 반환한다:

iOS weekdayIndex  요일
1 일요일
2 월요일
3 화요일
4 화요일
5 목요일
6 금요일
7 토요일

 

즉, offset은 단순히 날짜 증가를 위한 "반복자"이고,
weekdayIndex는 날짜(day)가 실제 달력에서 어떤 요일인지에 따라 정해진 값이다.


🔎 예시

예를 들어 interval.start = 2025-11-16 (일요일)이면:

 

1. offset = 0
→ 날짜: 2025-11-16
→ 요일: 일요일
→ weekdayIndex = 1

 

2. offset = 1
→ 날짜: 2025-11-17
→ 요일: 월요일
→ weekdayIndex = 2

 

3. offset = 2
→ 날짜: 2025-11-18
→ 요일: 화요일
→ weekdayIndex = 3

 

이런 식으로 offset 값과 weekdayIndex는 완전히 다른 개념이야.


✅ 2. 왜 extension에 init?(weekdayIndex:) 형태의 초기화를 사용했나?

바로 이 문제 때문이야:

 

📌 Calendar는 요일을 Int로 준다

 

하지만

 

📌 우리는 요일을 enum Weekday로 관리한다

Int → Weekday enum

 

이 변환이 자주 필요함.

그래서 아래처럼 생성자로 제공하는 것이 가장 Swift스러운 방법이야:

init?(weekdayIndex: Int) {
    switch weekdayIndex {
    case 1: self = .sun
    case 2: self = .mon
    case 3: self = .tue
    case 4: self = .wed
    case 5: self = .thu
    case 6: self = .fri
    case 7: self = .sat
    default: return nil
    }
}

 

✔️ init이 가장 좋은 이유 정리

1. Swift의 타입 변환 규칙과 동일하다

2. 코드 읽을 때 역할이 명확하다

3. 실패 가능성(nil)을 자연스러운 optional initializer로 표현할 수 있다

4. 호출이 깔끔하다:

if let weekday = Weekday(weekdayIndex: weekdayIndex) {
    dict[weekday] = day
}
728x90
LIST