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

📘 DiaryWriteViewModel – 설계 문서 (Logic Blueprint)

by 밤새는 탐험가89 2025. 12. 9.
728x90
SMALL

1. 클래스 개요

DiaryWriteViewModel은 감정일기 작성 과정에서 사용되는 모든 비즈니스 로직을 중앙에서 관리하는 ViewModel이다.
다음의 책임을 수행한다:

  • 화면 상태(UI State) 관리
  • 감정 선택 및 검증 로직 처리
  • 일기 데이터 수정(editableDiary) 관리
  • 다음 단계 이동 가능 여부 검증
  • ViewController에 errorMessage 전달해 Alert 표시 유도

UI 계층(ViewController / View)은 이 ViewModel의 상태 변화를 구독하여 반응하도록 설계되어 있다.

2. 주요 프로퍼티 및 역할 정의

 🧩 2.1 Dependencies

private let store: DiaryProviding
let mode: DiaryMode

 

  • 일기 저장소(DiaryStore)에 접근할 수 있도록 주입된 의존성
  • 생성/수정 모드를 나타내는 mode 포함
  • 저장/업데이트 시 store를 호출하도록 설계됨

 

🧩 2.2 UI State

@Published var uiState: DiaryEditorUIState

 

  • 화면 타이틀, 버튼 텍스트 등 UI 구성에 필요한 상태를 제공
  • VC는 이를 구독해 UI를 반영함

 

🧩 2.3 Data (Editable Diary)

@Published var editableDiary: EmotionDiaryModel
private let originalDiary: EmotionDiaryModel?

 

  • 감정일기 편집을 위한 실시간 작업 데이터
  • 원본 Diary를 보관(originalDiary)해 업데이트 시 비교/저장 가능
  • 감정, 상황, 생각, 행동 모두 여기에 저장됨

 

🧩 2.4 에러 메시지 전달

@Published var errorMessage: String?

 

 

  • 유효성 검사 실패 시 메시지를 발행(Publish)
  • VC는 이를 구독하여 Alert 띄움
  • ViewModel은 Alert 로직을 가지지 않는다 → MVVM 일관성 유지

 

🧩 2.5 감정 선택 가능 여부 (UI 제어)

@Published var canSelectEmotion: Bool = true

 

 

  • 특정 상황에서 감정 선택 UI를 잠시 비활성화할 수 있도록 제공
  • 현재는 사용 빈도가 낮지만 확장성을 위해 유지

 

3️⃣ 감정 선택 로직 (trySelectEmotion)

3.1 목적

  • 유저가 subEmotion을 탭할 때마다
    “이 선택이 유효한지” 판단하고
    결과에 따라 ViewModel 상태를 업데이트하거나 UI를 막는 역할.

3.2 처리 흐름

EmotionStepCell → trySelectEmotion → Return true/false → UI 반영 또는 Alert

 

 

3.3 세부 규칙

✔ Case 1: 아무것도 선택하지 않은 경우

if emotion.subEmotion.isEmpty { ... }

 

  • 감정을 0개 선택하는 상태는 허용
  • 하지만 다음 단계 이동 시에는 별도 검증(canProceedToNextStep)에서 막힘

✔ Case 2: 최대 선택 개수 초과

if emotion.subEmotion.count > 3

 

  • 3개 초과는 즉시 불허
  • UI는 변경되지 않음
  • errorMessage로 Alert 유도

✔ Case 3: 다른 카테고리 섞기 불가

if currentCategory != .none && currentCategory != emotion.category
  • 한 번 카테고리를 선택했다면
    그 카테고리 안에서만 subEmotion 선택 가능하도록 제한

✔ Case 4: 정상 선택

updateEmotion(emotion)

 

  • 감정 선택이 규칙을 만족하면 editableDiary에 반영
  • StepCell이 reloadItems를 통해 UI 갱신

 

4️⃣ 다음 단계 이동 유효성 검사 (canProceedToNextStep)

4.1 목적

유저가 "다음" 버튼을 눌렀을 때
해당 단계에서 필요한 최소 조건을 충족했는지 검사한다.

 

4.2 감정 단계(.emotion) 검증 규칙

if editableDiary.emotion.subEmotion.isEmpty {
    triggerError("최소한 1개의 감정을 선택해주세요!")
    return false
}

 

 

  • 감정 선택이 0개라면 다음 단계로 이동할 수 없다
  • 선택 시 trySelectEmotion에서는 허용하지만
    "다음 단계 전환"에서는 별도의 검증 절차로 처리함 → UX적으로 자연스러움

 

4.3 다른 단계(situation/thought/action)는 현재 패스

  • 필요 시 확장 가능
  • 이후 일기 내용 단계에서도 동일 패턴 유지 가능

 

5️⃣ 에러 처리(triggerError)

역할

  • 메시지를 errorMessage에 publish
  • VC는 이를 구독하여 Alert 표시
private func triggerError(_ message: String) {
    errorMessage = message
}

 

ViewModel은 Alert을 띄우지 않음 → UI 책임은 VC에게 있음
MVVM 아키텍처에서 매우 올바른 구조.

 

6️⃣ 전체 데이터/이벤트 흐름도

(유저 탭)
 EmotionCategoryCell
       ↓   (이벤트 전달)
 EmotionStepCell
       ↓   (candidate 생성)
 ViewModel.trySelectEmotion
       ↓   true/false
 EmotionStepCell UI 반영 or 유지
       ↓
 editableDiary.emotion 업데이트

 

 

그리고 다음 버튼 흐름:

Next 버튼터치
     ↓
ViewModel.canProceedToNextStep
     ↓ (false)
 Alert 표시
728x90
LIST