# 적자 탈출 가계부 데이터 모델 설계 ## 개요 '적자 탈출 가계부' 애플리케이션의 데이터 모델은 사용자의 재정 데이터를 효율적으로 저장, 관리, 분석할 수 있도록 설계되었습니다. 본 문서는 데이터베이스 스키마, 주요 엔티티 간의 관계, 그리고 데이터 접근 패턴에 대해 설명합니다. ## 데이터베이스 선택 ### 주요 데이터베이스: MongoDB MongoDB를 주요 데이터베이스로 선택한 이유: - **유연한 스키마**: 사용자별 맞춤형 카테고리, 태그 등 다양한 확장 가능성 지원 - **문서 지향적 구조**: 계층적 데이터(예: 거래 내역과 관련 메타데이터) 저장에 적합 - **확장성**: 사용자 증가에 따른 수평적 확장 용이 - **쿼리 성능**: 복잡한 집계 및 분석 쿼리 지원 ### 보조 데이터베이스: Redis Redis를 보조 데이터베이스로 활용: - **캐싱**: 자주 접근하는 데이터(예: 사용자 대시보드 요약) 캐싱 - **세션 관리**: 사용자 세션 및 인증 토큰 관리 - **실시간 데이터**: 알림 및 실시간 업데이트 관리 - **작업 큐**: 비동기 작업(예: 데이터 분석, 보고서 생성) 관리 ## 주요 데이터 엔티티 ### 1. 사용자 (Users) 사용자 계정 및 프로필 정보를 저장합니다. ```javascript { _id: ObjectId, // 사용자 고유 ID email: String, // 이메일 (로그인 ID) password: String, // 암호화된 비밀번호 name: String, // 사용자 이름 profileImage: String, // 프로필 이미지 URL phoneNumber: String, // 전화번호 (선택사항) dateOfBirth: Date, // 생년월일 (선택사항) gender: String, // 성별 (선택사항) occupation: String, // 직업 (선택사항) monthlyIncome: Number, // 월 평균 수입 financialGoals: [ // 재정 목표 목록 { _id: ObjectId, // 목표 ID name: String, // 목표 이름 targetAmount: Number, // 목표 금액 currentAmount: Number, // 현재 금액 deadline: Date, // 목표 기한 category: String, // 목표 카테고리 isCompleted: Boolean, // 완료 여부 createdAt: Date // 생성 일시 } ], preferences: { // 사용자 설정 currency: String, // 통화 단위 language: String, // 언어 설정 theme: String, // UI 테마 notificationSettings: { // 알림 설정 budgetAlerts: Boolean, // 예산 알림 transactionReminders: Boolean, // 거래 리마인더 weeklyReports: Boolean, // 주간 보고서 savingsTips: Boolean // 절약 팁 } }, subscriptionTier: String, // 구독 등급 (free, premium) subscriptionExpiresAt: Date, // 구독 만료일 createdAt: Date, // 계정 생성일 updatedAt: Date, // 최종 업데이트일 lastLoginAt: Date, // 최근 로그인일 isActive: Boolean, // 계정 활성화 상태 deactivatedAt: Date, // 계정 비활성화일 refreshToken: String // 리프레시 토큰 } ``` ### 2. 거래 내역 (Transactions) 사용자의 모든 수입, 지출, 이체 거래를 저장합니다. ```javascript { _id: ObjectId, // 거래 고유 ID userId: ObjectId, // 사용자 ID (참조) type: String, // 거래 유형 (income, expense, transfer) amount: Number, // 거래 금액 currency: String, // 통화 단위 categoryId: ObjectId, // 카테고리 ID (참조) subcategoryId: ObjectId, // 서브카테고리 ID (참조, 선택사항) paymentMethodId: ObjectId, // 결제 수단 ID (참조) accountId: ObjectId, // 계좌 ID (참조) description: String, // 거래 설명 memo: String, // 추가 메모 transactionDate: Date, // 거래 일시 location: { // 거래 위치 (선택사항) name: String, // 장소 이름 latitude: Number, // 위도 longitude: Number // 경도 }, tags: [String], // 태그 목록 attachments: [ // 첨부 파일 (영수증 등) { url: String, // 파일 URL type: String, // 파일 유형 name: String, // 파일 이름 uploadedAt: Date // 업로드 일시 } ], isRecurring: Boolean, // 정기 거래 여부 recurringDetails: { // 정기 거래 상세 (선택사항) frequency: String, // 빈도 (daily, weekly, monthly, yearly) interval: Number, // 간격 startDate: Date, // 시작일 endDate: Date, // 종료일 (선택사항) lastProcessedDate: Date // 마지막 처리일 }, status: String, // 상태 (pending, completed, cancelled) createdAt: Date, // 생성일 updatedAt: Date, // 수정일 deletedAt: Date, // 삭제일 (소프트 삭제) isDeleted: Boolean // 삭제 여부 } ``` ### 3. 카테고리 (Categories) 거래를 분류하기 위한 카테고리 정보를 저장합니다. ```javascript { _id: ObjectId, // 카테고리 고유 ID userId: ObjectId, // 사용자 ID (참조, null이면 기본 카테고리) name: String, // 카테고리 이름 type: String, // 카테고리 유형 (income, expense) icon: String, // 아이콘 식별자 color: String, // 색상 코드 isDefault: Boolean, // 기본 카테고리 여부 isActive: Boolean, // 활성화 상태 parentId: ObjectId, // 부모 카테고리 ID (참조, 선택사항) order: Number, // 표시 순서 createdAt: Date, // 생성일 updatedAt: Date // 수정일 } ``` ### 4. 예산 (Budgets) 사용자의 예산 설정 정보를 저장합니다. ```javascript { _id: ObjectId, // 예산 고유 ID userId: ObjectId, // 사용자 ID (참조) name: String, // 예산 이름 amount: Number, // 예산 금액 currency: String, // 통화 단위 period: String, // 기간 유형 (daily, weekly, monthly, yearly) startDate: Date, // 시작일 endDate: Date, // 종료일 categoryIds: [ObjectId], // 카테고리 ID 목록 (참조) isRecurring: Boolean, // 반복 여부 notificationThreshold: Number, // 알림 임계값 (%) createdAt: Date, // 생성일 updatedAt: Date, // 수정일 isActive: Boolean // 활성화 상태 } ``` ### 5. 계좌 (Accounts) 사용자의 금융 계좌 정보를 저장합니다. ```javascript { _id: ObjectId, // 계좌 고유 ID userId: ObjectId, // 사용자 ID (참조) name: String, // 계좌 이름 type: String, // 계좌 유형 (checking, savings, credit, investment) institutionName: String, // 금융 기관 이름 accountNumber: String, // 계좌 번호 (마스킹 처리) balance: Number, // 현재 잔액 currency: String, // 통화 단위 isLinked: Boolean, // 외부 API 연동 여부 externalId: String, // 외부 API 식별자 (선택사항) lastSyncAt: Date, // 마지막 동기화 일시 icon: String, // 아이콘 식별자 color: String, // 색상 코드 isDefault: Boolean, // 기본 계좌 여부 isActive: Boolean, // 활성화 상태 createdAt: Date, // 생성일 updatedAt: Date // 수정일 } ``` ### 6. 결제 수단 (PaymentMethods) 사용자의 결제 수단 정보를 저장합니다. ```javascript { _id: ObjectId, // 결제 수단 고유 ID userId: ObjectId, // 사용자 ID (참조) name: String, // 결제 수단 이름 type: String, // 유형 (cash, credit_card, debit_card, bank_transfer, mobile_payment) accountId: ObjectId, // 연결된 계좌 ID (참조, 선택사항) cardInfo: { // 카드 정보 (선택사항) lastFourDigits: String, // 카드 번호 마지막 4자리 expiryDate: String, // 만료일 cardNetwork: String // 카드 네트워크 (Visa, Mastercard 등) }, icon: String, // 아이콘 식별자 color: String, // 색상 코드 isDefault: Boolean, // 기본 결제 수단 여부 isActive: Boolean, // 활성화 상태 createdAt: Date, // 생성일 updatedAt: Date // 수정일 } ``` ### 7. 절약 챌린지 (SavingChallenges) 사용자의 절약 챌린지 정보를 저장합니다. ```javascript { _id: ObjectId, // 챌린지 고유 ID title: String, // 챌린지 제목 description: String, // 챌린지 설명 type: String, // 챌린지 유형 (system, custom) creatorId: ObjectId, // 생성자 ID (참조, system이면 null) targetAmount: Number, // 목표 절약 금액 duration: Number, // 기간 (일 단위) difficulty: String, // 난이도 (easy, medium, hard) categoryIds: [ObjectId], // 관련 카테고리 ID 목록 (참조) tips: [String], // 절약 팁 목록 imageUrl: String, // 챌린지 이미지 URL isPublic: Boolean, // 공개 여부 participantCount: Number, // 참여자 수 successRate: Number, // 성공률 (%) createdAt: Date, // 생성일 updatedAt: Date, // 수정일 isActive: Boolean // 활성화 상태 } ``` ### 8. 사용자 챌린지 참여 (UserChallenges) 사용자의 챌린지 참여 정보를 저장합니다. ```javascript { _id: ObjectId, // 참여 고유 ID userId: ObjectId, // 사용자 ID (참조) challengeId: ObjectId, // 챌린지 ID (참조) startDate: Date, // 시작일 endDate: Date, // 종료일 targetAmount: Number, // 개인 목표 금액 currentAmount: Number, // 현재 절약 금액 status: String, // 상태 (in_progress, completed, failed) progress: Number, // 진행률 (%) dailyLogs: [ // 일일 기록 { date: Date, // 날짜 amount: Number, // 절약 금액 note: String // 메모 } ], completedAt: Date, // 완료일 (선택사항) reward: { // 보상 정보 (선택사항) type: String, // 보상 유형 description: String, // 보상 설명 claimedAt: Date // 수령일 }, createdAt: Date, // 생성일 updatedAt: Date // 수정일 } ``` ### 9. 재정 분석 (FinancialAnalytics) 사용자의 재정 분석 데이터를 저장합니다. ```javascript { _id: ObjectId, // 분석 고유 ID userId: ObjectId, // 사용자 ID (참조) period: String, // 기간 유형 (daily, weekly, monthly, yearly) startDate: Date, // 시작일 endDate: Date, // 종료일 totalIncome: Number, // 총 수입 totalExpense: Number, // 총 지출 netCashflow: Number, // 순 현금 흐름 savingsRate: Number, // 저축률 (%) categoryBreakdown: [ // 카테고리별 지출 분석 { categoryId: ObjectId, // 카테고리 ID (참조) amount: Number, // 금액 percentage: Number, // 비율 (%) trend: Number // 전기 대비 변화율 (%) } ], topExpenses: [ // 주요 지출 항목 { transactionId: ObjectId, // 거래 ID (참조) amount: Number, // 금액 description: String, // 설명 date: Date // 날짜 } ], trends: { // 추세 분석 incomeGrowth: Number, // 수입 증가율 (%) expenseGrowth: Number, // 지출 증가율 (%) savingsGrowth: Number // 저축 증가율 (%) }, financialHealthScore: { // 재정 건강 점수 overall: Number, // 종합 점수 budgetAdherence: Number, // 예산 준수 점수 savingsRate: Number, // 저축률 점수 debtManagement: Number, // 부채 관리 점수 expenseEfficiency: Number // 지출 효율성 점수 }, insights: [ // 인사이트 목록 { type: String, // 인사이트 유형 description: String, // 설명 potentialSavings: Number, // 잠재적 절약 금액 priority: String // 우선순위 (high, medium, low) } ], createdAt: Date, // 생성일 updatedAt: Date // 수정일 } ``` ### 10. 알림 (Notifications) 사용자에게 전송되는 알림 정보를 저장합니다. ```javascript { _id: ObjectId, // 알림 고유 ID userId: ObjectId, // 사용자 ID (참조) type: String, // 알림 유형 (budget_alert, transaction_reminder, saving_tip, etc) title: String, // 알림 제목 message: String, // 알림 내용 data: { // 관련 데이터 entityType: String, // 엔티티 유형 (budget, transaction, challenge, etc) entityId: ObjectId, // 엔티티 ID (참조) action: String // 필요한 액션 }, isRead: Boolean, // 읽음 여부 readAt: Date, // 읽은 일시 isActionTaken: Boolean, // 액션 수행 여부 actionTakenAt: Date, // 액션 수행 일시 expiresAt: Date, // 만료일 (선택사항) priority: String, // 우선순위 (high, medium, low) createdAt: Date, // 생성일 updatedAt: Date // 수정일 } ``` ## 데이터 관계 다이어그램 ``` +-------------+ +----------------+ +-------------+ | Users |------>| Transactions |<------| Categories | +-------------+ +----------------+ +-------------+ | | | | | | v v v +-------------+ +----------------+ +-------------+ | Accounts |------>| PaymentMethods | | Budgets | +-------------+ +----------------+ +-------------+ | | | | v v +-------------+ +----------------+ +-------------+ | UserChallenges|<---->|SavingChallenges| |FinancialAnalytics| +-------------+ +----------------+ +-------------+ | | v +-------------+ |Notifications | +-------------+ ``` ## 인덱싱 전략 효율적인 쿼리 성능을 위한 인덱스 설계: ### 사용자 컬렉션 - `email`: 로그인 및 사용자 조회 - `subscriptionTier`, `subscriptionExpiresAt`: 구독 관리 ### 거래 내역 컬렉션 - `userId`: 사용자별 거래 조회 - `userId` + `transactionDate`: 날짜별 거래 조회 - `userId` + `categoryId`: 카테고리별 거래 조회 - `userId` + `type`: 수입/지출별 조회 - `userId` + `isRecurring`: 정기 거래 조회 ### 카테고리 컬렉션 - `userId`: 사용자별 카테고리 조회 - `userId` + `type`: 수입/지출 카테고리 조회 ### 예산 컬렉션 - `userId`: 사용자별 예산 조회 - `userId` + `period` + `startDate`: 기간별 예산 조회 ### 계좌 컬렉션 - `userId`: 사용자별 계좌 조회 - `userId` + `type`: 계좌 유형별 조회 ### 절약 챌린지 컬렉션 - `isPublic`: 공개 챌린지 조회 - `difficulty`: 난이도별 챌린지 조회 ### 사용자 챌린지 참여 컬렉션 - `userId`: 사용자별 챌린지 참여 조회 - `userId` + `status`: 상태별 챌린지 조회 - `challengeId`: 챌린지별 참여자 조회 ### 재정 분석 컬렉션 - `userId`: 사용자별 분석 조회 - `userId` + `period` + `startDate`: 기간별 분석 조회 ### 알림 컬렉션 - `userId`: 사용자별 알림 조회 - `userId` + `isRead`: 읽지 않은 알림 조회 - `userId` + `priority`: 우선순위별 알림 조회 ## 데이터 접근 패턴 주요 사용 사례에 따른 데이터 접근 패턴: ### 1. 대시보드 로딩 - 사용자 기본 정보 조회 - 최근 거래 내역 조회 (제한된 수) - 현재 월 예산 대비 지출 현황 조회 - 재정 건강 점수 조회 - 읽지 않은 알림 조회 ### 2. 거래 내역 조회 - 기간별 거래 내역 페이지네이션 조회 - 카테고리별 필터링 - 금액별 정렬 ### 3. 예산 관리 - 현재 활성 예산 조회 - 카테고리별 예산 대비 지출 현황 조회 - 예산 초과 카테고리 식별 ### 4. 재정 분석 - 기간별 수입/지출 추이 조회 - 카테고리별 지출 분석 조회 - 전월 대비 변화율 계산 - 절약 인사이트 생성 ### 5. 절약 챌린지 - 추천 챌린지 조회 - 사용자 참여 챌린지 상태 조회 - 챌린지 진행 상황 업데이트 ## 데이터 마이그레이션 전략 애플리케이션 발전에 따른 데이터 마이그레이션 전략: ### 1. 스키마 변경 관리 - 하위 호환성 유지: 필드 추가 시 기본값 설정 - 버전 관리: 스키마 버전 필드 추가 - 점진적 마이그레이션: 대규모 데이터 세트의 경우 배치 처리 ### 2. 데이터 백업 - 정기적인 전체 백업: 일일 단위 - 증분 백업: 시간 단위 - 지리적 복제: 재해 복구 대비 ### 3. 데이터 보존 정책 - 트랜잭션 데이터: 7년 보존 - 분석 데이터: 집계 데이터는 영구 보존, 원시 데이터는 2년 보존 - 사용자 활동 로그: 1년 보존 - 삭제된 계정 데이터: 30일 후 완전 삭제 ## 데이터 보안 사용자 재정 데이터 보호를 위한 보안 조치: ### 1. 데이터 암호화 - 저장 데이터(Data at Rest): AES-256 암호화 - 전송 중 데이터(Data in Transit): TLS 1.3 - 민감 정보(계좌 번호, 카드 정보): 필드 수준 암호화 ### 2. 접근 제어 - 역할 기반 접근 제어(RBAC) 구현 - 최소 권한 원칙 적용 - API 키 및 토큰 관리 ### 3. 감사 및 모니터링 - 데이터 접근 로깅 - 이상 행동 감지 - 정기적인 보안 감사 ## 성능 최적화 대규모 데이터 처리를 위한 성능 최적화 전략: ### 1. 쿼리 최적화 - 적절한 인덱스 사용 - 프로젝션을 통한 필요 필드만 조회 - 페이지네이션 구현 ### 2. 캐싱 전략 - 자주 접근하는 데이터 Redis 캐싱 - 사용자별 대시보드 데이터 캐싱 - 분석 결과 캐싱 ### 3. 데이터 집계 - 실시간 집계 대신 사전 계산된 집계 데이터 활용 - 배치 처리를 통한 분석 데이터 생성 - 시계열 데이터 최적화 ## 결론 '적자 탈출 가계부' 애플리케이션의 데이터 모델은 사용자의 재정 데이터를 효율적으로 관리하고 분석하기 위해 설계되었습니다. MongoDB의 유연한 스키마를 활용하여 다양한 사용자 요구사항을 수용하고, Redis를 통한 캐싱으로 성능을 최적화하였습니다. 이 데이터 모델은 초기 MVP 출시 후 사용자 피드백과 실제 사용 패턴에 따라 지속적으로 개선될 예정입니다. 특히 AI 기반 분석 및 추천 기능 강화를 위한 데이터 구조 최적화가 향후 중점적으로 이루어질 계획입니다.