지난 포스트에서는 DiaryStore를 통해 감정일기 데이터를 전역에서 관리하는
SSOT(Single Source of Truth, 단일 데이터 출처) 구조를 완성했습니다.
이번에는 이 DiaryStore를 실제 화면(View) 에서 어떻게 사용할지,
즉, ViewModel을 어떻게 나누고 설계할지에 대해 다뤄봅니다.
🎯 핵심 질문
DiaryStore가 전역 상태를 관리한다면,
그 데이터를 사용하는 ViewModel은 “기능 단위”로 만들어야 할까,
아니면 “화면 단위”로 만들어야 할까?
🧭 결론부터 — “화면 단위 ViewModel”이 정답이다.
✅ “데이터 관리”는 DiaryStore
✅ “화면 상태 관리”는 “화면 단위 ViewModel”
이 조합이 MVVM 아키텍처의 본질을 가장 깔끔하게 살린 구조입니다.
🧩 기능 단위 vs 화면 단위 ViewModel
| 구분 | 기능 단위 | 화면 단위 |
| 장점 | 여러 곳에서 재사용 가능 | View와 1:1 관계, 구조 명확 |
| 단점 | 기능 간 의존성이 얽힘 | 일부 코드 중복 가능 |
| 적합도 | 대규모 모듈, 복잡한 서비스 | ✅ Core Data 기반 개인 앱에 가장 적합 |
| 예시 | EmotionAnalysisViewModel, DiarySearchViewModel |
HomeViewModel, DiaryListViewModel, DiaryEditorViewModel |
👉 결론적으로, 지금 단계에서는 “화면(ViewController) 기준으로
ViewModel을 분리”하는 게 가장 자연스럽고 유지보수가 쉽습니다.
🧱 프로젝트 구조 예시
ViewModel/
├─ SSOT/
│ └─ DiaryStore.swift // 전역 데이터 관리 (Single Source of Truth)
│
├─ Home/
│ └─ HomeViewModel.swift // 홈화면: 명언, 최근 일기, 주간 감정 통계
│
├─ DiaryList/
│ └─ DiaryListViewModel.swift // 전체 일기 목록 관리
│
├─ DiaryDetail/
│ └─ DiaryDetailViewModel.swift // 일기 상세 조회
│
└─ DiaryEditor/
└─ DiaryEditorViewModel.swift // 일기 작성 및 수정
각 화면(ViewController)은 자신만의 ViewModel을 가지며,
공통 데이터는 DiaryStore에서 받아옵니다.
🔄 데이터 흐름 요약
Core Data ←→ DiaryStore (SSOT)
↓
HomeViewModel / DiaryListViewModel / DiaryEditorViewModel
↓
View(UI)
- DiaryStore는 앱 전체에서 하나만 존재합니다.
- ViewModel은 오직 구독(subscribe) 만 합니다.
- Core Data의 상태가 바뀌면 → DiaryStore가 감지 → ViewModel이 갱신 → View(UI) 반영
🍋 HomeViewModel 구현 예시
import Combine
import Foundation
final class HomeViewModel {
private let store: DiaryProviding
private var cancellables = Set<AnyCancellable>()
@Published private(set) var recentDiary: EmotionDiaryModel?
@Published private(set) var weeklySummary: [EmotionCategory: Int] = [:]
init(store: DiaryProviding = DiaryStore.shared) {
self.store = store
// DiaryStore의 Publisher를 구독
store.diariesPublisher
.sink { [weak self] diaries in
self?.recentDiary = diaries.first
self?.weeklySummary = store.countByEmotion(inWeekOf: Date())
}
.store(in: &cancellables)
}
}
🧠 동작 방식
- DiaryStore가 Core Data에서 변화를 감지하면 diariesPublisher가 새로운 데이터를 발행(emit)
- HomeViewModel은 이를 구독하고 필요한 데이터(recentDiary, weeklySummary)만 가공해서 보관
- View(UI)는 @Published 프로퍼티를 감시하면서 자동으로 갱신됨