프로젝트 맥락
본 글은 SwiftUI로 Apple Developer Academy_Challenge 2에서 개발 중인 ‘Re:ToU(오늘의 너)’ 앱을 기반으로 작성되었습니다.
이 앱은 사용자가 하루에 하나씩 감정과 회고를 기록하고, 한 달 단위로 감정 통계를 분석해주는 뷰를 제공합니다.
통계는 시각적으로 직관적이어야 하고,
데이터를 바탕으로 간단한 피드백 메시지를 제공함으로써 사용자 스스로를 돌아볼 수 있게 하는 것이 핵심 목표였습니다.
기능 설명
감정 통계 뷰는 다음과 같은 기능을 포함합니다.
- 월별 감정 분포 분석: 감정별 빈도를 계산
- 시각화 차트: 감정별 비율을 막대그래프 등으로 표현
- 간단한 피드백 문구 출력: 가장 많이 느낀 감정을 기준으로 피드백 문장을 출력
시도 동기
처음에는 리스트 뷰에서 날짜를 스크롤하며 감정 상태를 추적하는 방식이었지만,
한눈에 감정의 흐름이나 주된 경향을 파악하기 어려웠습니다.
그래서 월별 통계 화면을 추가하고,
ReflectionStorage 내 데이터를 집계해 시각화하는 방식으로 전환하게 되었습니다.
문제 발견
감정 통계를 구현하면서 다음과 같은 문제를 겪었습니다.
- 감정 데이터는 enum인데 저장은 문자열로 되어 있음
- → 집계 시 문자열을 다시 enum으로 변환해야 정확히 비교 가능
- 데이터 누락 혹은 감정 선택하지 않고 작성된 회고 예외 처리 필요
- 사용자 피드백 문구의 기준 설정
- → 어떤 감정을 기준으로 어떤 문장을 보여줄지 고민 필요
문제 해결
1. 감정별 집계 로직 (ViewModel 또는 ReflectionStorage 내부)
func emotionCounts(forMonth year: Int, month: Int) -> [EmotionType: Int] {
let calendar = Calendar.current
let filtered = reflections.filter {
calendar.component(.year, from: $0.date) == year &&
calendar.component(.month, from: $0.date) == month
}
var counts: [EmotionType: Int] = [:]
for reflection in filtered {
if let emotion = EmotionType(rawValue: reflection.emotion) {
counts[emotion, default: 0] += 1
}
}
return counts
}
2. 가장 많이 등장한 감정 도출 및 피드백 메시지 생성
func feedbackMessage(from counts: [EmotionType: Int]) -> String {
guard let (topEmotion, count) = counts.max(by: { $0.value < $1.value }) else {
return "이번 달은 회고가 충분하지 않았어요. 다음 달엔 더 많이 기록해봐요!"
}
switch topEmotion {
case .happy: return "이번 달은 기분 좋은 날이 많았어요 😊"
case .sad: return "조금은 힘든 시간이었네요. 잘 버텼어요."
case .angry: return "화를 많이 느꼈어요. 감정을 건강하게 표현해봐요."
case .surprised: return "뜻밖의 일이 많았던 한 달이었어요!"
case .neutral: return "무난한 하루들이 이어졌어요. 평온한 달이었네요."
}
}
3. UI에서 시각화 (예시: 막대 그래프)
Charts 프레임워크 또는 SwiftUI 뷰만으로 구성 가능.
예시:
ForEach(EmotionType.allCases, id: \.self) { emotion in
let count = emotionCounts[emotion, default: 0]
HStack {
Text(emotion.rawValue)
Rectangle()
.fill(Color.orange)
.frame(width: CGFloat(count) * 20, height: 20)
Text("\(count)")
}
}
비슷한 분석 방식 비교
방식 설명 장점 단점
단순 통계 수치 나열 | 감정별 횟수만 표시 | 구현 쉬움 | 시각적 효과 없음 |
막대그래프 형태 | 감정별 비율을 시각화 | 직관적, 비교 쉬움 | 커스터마이징 필요 |
원형 차트 (Pie Chart) | 전체 중 비율로 표현 | 집중 포인트 제공 | 많은 감정 종류엔 부적합 |
텍스트 피드백만 제공 | 메시지로 요약 | 간결, 친근함 | 통계적 신뢰 낮음 |
느낀 점
단순히 회고 데이터를 모으는 것도 중요하지만,
그 데이터를 기반으로 사용자에게 무엇을 보여줄 수 있을지 고민하는 것이 UX의 본질이라는 걸 느꼈습니다.
피드백 메시지를 자동으로 생성하는 구조는 작지만,
사용자에게 “기록이 나를 이해하게 만든다”는 감정을 줄 수 있는 강력한 장치가 되었습니다.
또한 감정 통계는 앞으로 앱에서 확장할 수 있는 영역이 많아
시각화 컴포넌트 구성, 애니메이션 효과, AI 분석 등으로 발전시킬 여지도 충분하다고 생각합니다.
'iOS & SwiftUI' 카테고리의 다른 글
SwiftUI 앱에서 Face ID / Touch ID 인증 구현하기 (1) | 2025.05.14 |
---|---|
SwiftUI에서 날짜 필터링 및 회고 리스트 정렬 구조 설계하기 (0) | 2025.05.10 |
SwiftUI에서 회고 데이터 모델 설계와 감정/내용 저장 방식 (2) | 2025.05.06 |
SwiftUI에서 작성/수정 화면을 분리하고 전환 흐름 구성하기 (2) | 2025.05.06 |
SwiftUI에서 감정 이모지 선택 UI 구현하기: HStack 기반 구조 (2) | 2025.05.05 |