본문 바로가기

SwiftUI에서 감정 통계 뷰 설계 및 사용자 피드백 표시 방식

@Prof.SSong2025. 5. 10. 16:51
728x90

프로젝트 맥락

 

본 글은 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 분석 등으로 발전시킬 여지도 충분하다고 생각합니다.

 

728x90
목차