본문 바로가기
한눈가계부/데이터 모델

📱 iOS 가계부 앱 개발기: 데이터 모델 설계 파헤치기 ✨

by 밤새는 탐험가89 2025. 8. 24.
728x90
SMALL

안녕하세요! iOS 가계부 앱을 만들며 어떻게 데이터 모델을 설계했는지 그 과정을 공유해 보려고 합니다.

앱의 뼈대가 되는 데이터 모델은 단순히 정보를 담는 그릇이 아니라, 앱의 안정성과 확장성을 결정하는 중요한 요소인데요.

제가 설계한 ExpenseModel과 관련 타입들을 함께 살펴볼까요? 😊


1. 가계부의 핵심, ExpenseModel 클래스 💰

가계부의 가장 기본은 '수입'과 '지출' 같은 거래 내역을 기록하는 것이죠.

저는 이 개별 거래 내역 하나하나를 저장하기 위해 ExpenseModel이라는 클래스를 만들었습니다.

class ExpenseModel {
    let id: UUID
    var transaction: TransactionType
    var category: String 
    var amount: Int
    var image: UIImage?
    var date: Date
    var memo: String?
    
    // 반복 기능 설정
    var isRepeated: Bool?
    var repeatCycle: RepeatCycle?

    init(id: UUID = UUID(),
         transaction: TransactionType,
         category: String,
         amount: Int,
         image: UIImage? = nil,
         date: Date = Date(),
         memo: String,
         isRepeated: Bool = false,
         repeatCycle: RepeatCycle = .none
    ) {
        self.id = id
        self.transaction = transaction
        self.category = category
        self.amount = amount
        self.image = image
        self.date = date
        self.memo = memo
        self.isRepeated = isRepeated
        self.repeatCycle = repeatCycle
    }
}

 

🔍 왜 class를 사용했을까?

 보통 iOS 개발에서 데이터 모델은 struct를 많이 사용하지만, 저는 Core Data나 Firebase 같은 데이터베이스와 연동을 염두에 두고 class를 선택했어요.

class는 참조 타입(Reference Type)이라 데이터베이스 객체와 연결하기가 훨씬 용이하거든요.

데이터를 수정할 때 여러 곳에서 변경 사항을 실시간으로 반영할 수 있다는 장점도 있습니다.


2. 깔끔한 분류를 위한 enum 타입 🌈

거래 내역의 종류(수입/지출)나 반복 주기를 관리하기 위해 enum을 활용했습니다. 덕분에 코드가 훨씬 안전하고 명확해졌죠!

 

TransactionType (거래 종류)

이 enum은 거래가 수입인지 지출인지를 구분하는 역할을 해요.

여기에 categoryOptions와 categoryImageMap이라는 계산 속성을 추가해서, 사용자가 수입을 선택하면 수입 카테고리만, 지출을 선택하면 지출 카테고리만 보여주도록 만들었습니다.

enum TransactionType: String {
    case income
    case expense

    var categoryOptions: [String] {
        switch self {
        case .income:
            return [
                NSLocalizedString("category_salary", comment: ""),
                // ... (생략)
                NSLocalizedString("category_other_income", comment: "")
            ]
        case .expense:
            return [
                NSLocalizedString("category_food", comment: ""),
                // ... (생략)
                NSLocalizedString("category_others", comment: "")
            ]
        }
    }
    
    var categoryImageMap: [String: String] {
        // ... (카테고리에 맞는 이미지 파일 이름 매핑)
    }
}

 

🔍 왜 category는 String일까?

ExpenseModel의 category를 String으로 정의한 것도 데이터베이스 연동 때문이에요.

데이터베이스에 바로 문자열로 저장하는 것이 더 간단하거든요.

이 방식은 나중에 사용자가 나만의 커스텀 카테고리를 추가할 수 있는 기능을 만들 때도 유연하게 대처할 수 있다는 장점이 있습니다.


RepeatCycle (반복 주기)

월세나 구독료처럼 주기적으로 발생하는 거래를 관리하기 위한 enum입니다.

enum RepeatCycle: String, CaseIterable, Codable {
    case none, daily, weekly, monthly, yearly
    
    var title: String {
        switch self {
        case .none:
            return NSLocalizedString("repeat_none", comment: "No repeat option")
        // ... (나머지 케이스)
        }
    }
}

 

CaseIterable 덕분에 daily, weekly 같은 모든 반복 주기를 쉽게 목록으로 가져올 수 있고, Codable을 채택해 데이터 저장 및 불러오기도 아주 간편해졌어요.


3. 마무리하며: 견고한 설계가 핵심! 🏗️

이렇게 class와 enum을 적절히 조합하여 가계부 앱의 데이터 모델을 설계했습니다.

개발 초기 단계에서부터 데이터베이스 연동과 사용자 편의성을 고려하니, 앞으로 기능을 확장해 나갈 때 훨씬 수월할 것 같아요. 이 글이 iOS 개발에 관심 있는 분들께 작은 도움이 되었으면 좋겠습니다!

읽어주셔서 감사합니다. 😊

728x90
LIST