728x90
SMALL
– weeklySummary 함수 분석과 고차함수 filter 완전 이해하기
🧭 이 글의 목적
iOS 앱에서 주간 단위로 수입과 지출을 요약해서 보여주는 화면을 만들고 싶을 때, 아래처럼 날짜별로 정리된 데이터가 필요합니다.
[
("Mon", 12000.0, 3000.0),
("Tue", 0.0, 5500.0),
("Wed", 0.0, 0.0),
...
("Sun", 5000.0, 10000.0)
]
이번 글에서는 이를 가능하게 해주는 weeklySummary라는 함수를 소개하고, 그 핵심인 고차함수 filter의 사용 이유와 구조를 상세히 분석합니다.
✅ weeklySummary 함수 – 무슨 역할을 할까?
🔹 함수 정의
func weeklySummary(in baseDate: Date) -> [(day: String, income: Double, expense: Double)]
🔹 주요 목적
- 기준 날짜(baseDate)가 속한 "한 주간의 시작일(월요일)"을 계산
- 월요일부터 일요일까지 반복하며
- 각 날짜에 해당하는 수입(income)과 지출(expense) 총합을 구함
- 결과를 (요일 문자열, 수입 총합, 지출 총합) 튜플 형태로 반환
이 함수는 주간 요약 통계를 보여주기 위한 데이터 소스로 매우 유용하며, 그래프, 표, 리스트 UI 등에 바로 활용 가능합니다.
🧩 함수 전체 코드
func weeklySummary(in baseDate: Date) -> [(day: String, income: Double, expense: Double)] {
let calendar = Calendar.current
let startOfWeek = calendar.date(from: calendar.dateComponents([.yearForWeekOfYear, .weekOfYear], from: baseDate))!
var result: [(String, Double, Double)] = []
let formatter = DateFormatter()
formatter.dateFormat = "EEE"
for i in 0..<7 {
guard let day = calendar.date(byAdding: .day, value: i, to: startOfWeek) else { continue }
let incomeForDay = transactions.filter {
$0.transaction == .income && calendar.isDate($0.date, inSameDayAs: day)
}.map { Double($0.amount) }.reduce(0, +)
let expenseForDay = transactions.filter {
$0.transaction == .expense && calendar.isDate($0.date, inSameDayAs: day)
}.map { Double($0.amount) }.reduce(0, +)
result.append((formatter.string(from: day), incomeForDay, expenseForDay))
}
return result
}
❇️ transactions는 ExpenseModel 타입의 배열로, 사용자의 모든 기록 데이터를 담고 있습니다.
🔍 핵심: filter 고차함수 분석
✳️ 이 부분이 핵심입니다
let incomeForDay = transactions.filter {
$0.transaction == .income && calendar.isDate($0.date, inSameDayAs: day)
}.map { Double($0.amount) }.reduce(0, +)
💡 이 코드는 무슨 일을 할까?
- transactions 배열 중에서
- 수입 항목이면서
- 날짜가 "현재 요일(day)"와 같은 것만 골라냄(filter)
- 그리고 해당 항목들의 amount 값을
- Double로 변환(map) 후
- 합산(reduce)
📎 filter 전 vs 후 비교
🔸 filter 사용 전 (일반 반복문 방식)
var incomeForDay = 0.0
for item in transactions {
if item.transaction == .income && calendar.isDate(item.date, inSameDayAs: day) {
incomeForDay += Double(item.amount)
}
}
- 절차적 방식 (명확하지만 반복될수록 코드가 길어짐)
- 수입이면서 해당 날짜와 같은 날인지 조건문으로 판별
🔹 filter 사용 후 (함수형 스타일)
let incomeForDay = transactions.filter {
$0.transaction == .income && calendar.isDate($0.date, inSameDayAs: day)
}.map { Double($0.amount) }.reduce(0, +)
- filter: 조건에 맞는 데이터만 추려냄
- map: Int → Double 변환
- reduce: 합계 구함
- 한 줄로 간결하고 선언적 (무엇을 하는지 바로 드러남)
🧪 실제 예시로 이해해보기
transactions = [
ExpenseModel(transaction: .income, amount: 1000, date: "2025-07-29"),
ExpenseModel(transaction: .expense, amount: 500, date: "2025-07-29"),
ExpenseModel(transaction: .income, amount: 2000, date: "2025-07-29"),
ExpenseModel(transaction: .income, amount: 3000, date: "2025-07-28")
]
let day = "2025-07-29"
🔍 filter 적용 결과
// 수입 && 7/29
transactions.filter {
$0.transaction == .income && calendar.isDate($0.date, inSameDayAs: day)
}
// 결과:
[
ExpenseModel(transaction: .income, amount: 1000, date: "2025-07-29"),
ExpenseModel(transaction: .income, amount: 2000, date: "2025-07-29")
]
✨ 마치며
이처럼 filter는 실무에서 매우 강력한 도구입니다.
조건에 따라 데이터를 추려야 할 때, map, reduce와 조합하면 훨씬 깔끔한 코드로 결과를 만들 수 있습니다.
특히 날짜 기반 통계를 처리하는 앱(가계부, 캘린더, 통계 등)에서 자주 쓰이니 꼭 익혀두세요!

728x90
LIST
'Project > ReceiptMind' 카테고리의 다른 글
| ✅ 앱 수정 후 재심사 제출하는 방법 (App Store Connect) (3) | 2025.07.30 |
|---|---|
| ❌ 앱 심사 거절 사례: Guideline 5.1.1 Privacy – Purpose String 부족 (1) | 2025.07.30 |
| 🧾 계산기 구현하기 (0) | 2025.07.17 |
| 💰 iOS 가계부 UI 구현기 – 선택된 항목에 따라 separator 색상 바꾸기 (1) | 2025.07.17 |
| 🤷 별도의 선택 UI를 띄우고, 값을 보여주는 용도라면? UILabel vs UITextField (2) | 2025.07.17 |