2025. 12. 8. 16:47ㆍAI 개발
개요
이 문서는 User Phase Service 개발 과정에서의 고민, 논의, 그리고 최종 결정 사항을 정리한 것입니다.
1. 서비스 위치 및 구조 결정
고민 사항
- Engine vs Service: backend/engine/에 둘지, backend/app/에 둘지?
- 서비스 이름: “user_pattern” vs “user_phase”
결정
- 위치: backend/app/user_phase/ (Service로 구현)
- 이유:
- 비즈니스 로직 서비스이므로 app/ 폴더가 적합
- Engine은 AI/ML 모델용, Service는 사용자 데이터 관리용
- 이름: “user_phase” (현재 상태 중심)
- 이유: “패턴 분석”보다는 “현재 Phase 판별”이 핵심 기능
구조
backend/app/user_phase/
├── __init__.py
├── models.py # Pydantic 모델
├── service.py # 비즈니스 로직
└── routes.py # API 엔드포인트
2. 데이터베이스 설계 결정
2.1. 테이블 구조
고민: 단일 테이블 vs OS별 테이블 분리
옵션 1: OS별 테이블 분리
TB_APPLE_HEALTH_LOGS
TB_ANDROID_HEALTH_LOGS
옵션 2: 통합 테이블 (선택)
TB_HEALTH_LOGS (SOURCE_TYPE으로 구분)
결정: 옵션 2 (통합 테이블)
- 이유:
- Phase 계산 시 두 테이블 JOIN 불필요
- 사용자가 기기 변경 시 데이터 분산 방지
- 확장성 (Fitbit, Samsung Health 등 추가 용이)
- 코드 중복 방지
2.2. 데이터 저장 방식
고민: 핵심 데이터만 vs 원본 데이터 전체
옵션 1: 핵심 데이터만
SLEEP_END_TIME
STEP_COUNT
# Phase 계산에 필요한 최소 데이터만
옵션 2: 핵심 + 원본 (선택)
SLEEP_END_TIME # 빠른 조회용STEP_COUNT
RAW_DATA (JSON) # 원본 데이터 전체
결정: 옵션 2 (하이브리드)
- 이유:
- Phase 계산은 빠르게 (인덱싱된 컬럼 사용)
- 나중에 다른 기능 개발 가능 (수면 질 분석, 심박수 모니터링 등)
- 데이터 손실 없음
2.3. 갱년기 특화 데이터
고민: 어떤 건강 데이터를 수집할까?
타겟: 갱년기 여성
고려 사항:
- Apple HealthKit vs Android Health Connect 공통 데이터만
- 체온 데이터: iOS만 지원 → 제외 (Android 차별 방지)
결정: 공통 데이터만 사용
# 수면SLEEP_DURATION_HOURS
SLEEP_START_TIME, SLEEP_END_TIME
# 심혈관HEART_RATE_AVG
HEART_RATE_RESTING
HEART_RATE_VARIABILITY (HRV)
# 활동량STEP_COUNT
ACTIVE_MINUTES
EXERCISE_MINUTES
CALORIES_BURNED
DISTANCE_KM
제외한 데이터:
- BODY_TEMPERATURE: Android Health Connect 미지원
- 이유: iOS/Android 공평성 유지
2.4. NULL 처리
고민: 모든 필드를 필수로 할까?
결정: 대부분 Optional (nullable=True)
- 이유:
- 사용자가 건강 앱을 사용하지 않을 수 있음
- 일부 데이터만 있어도 Phase 계산 가능
- 점진적 데이터 수집 가능
필수 필드:
- USER_ID, LOG_DATE, SOURCE_TYPE, CREATED_AT
Optional 필드:
- 모든 건강 데이터 (수면, 심박수, 활동량 등)
3. Phase 계산 로직 결정
3.1. Fallback 전략
고민: 어떻게 Fallback을 구성할까?
초기 계획:
- 실제 데이터
- User Setting
- 시스템 기본값 (07:00)
문제점:
- 시스템 기본값은 사용자마다 다를 수 있음
- 모든 사용자가 설정을 입력해야 함
최종 결정: 2단계 Fallback (패턴 기반)
- 패턴 분석 결과 (최우선)
- TB_USER_PATTERN_SETTINGS 조회
- 오늘이 평일인지 주말인지 구분
- 월요일에 계산된 평일/주말 평균 기상 시간으로 Phase 계산
- data_source: “pattern_analysis” (패턴 분석 완료 시) 또는 “user_setting” (수동 설정만 있을 시)
- 에러 처리 (설정 없음)
- HTTPException 반환
- “온보딩 필요 또는 건강 데이터 동기화 허용” 메시지
이유:
- 패턴 평균값 기반으로 일관된 Phase 계산 (알림 발송에 적합)
- 평일/주말 구분으로 더 정확한 Phase 계산
- 실시간 데이터는 나중에 추가 가능 (테스트 후 결정)
- 사용자 수동 설정은 건강 데이터 비동의 시 Fallback으로 사용
3.2. 패턴 분석 방식
고민: 언제 패턴을 분석할까?
옵션 1: 매일 자동
- 매일 자정에 자동 분석
옵션 2: 주 1회 (선택)
- 월요일마다 또는 7일마다
옵션 3: 수동 트리거
- 사용자가 요청할 때만
결정: 주 1회 자동 실행 (월요일) + 수동 트리거
- 자동 실행 조건:
- 월요일에만 자동 실행
- 지난 7일(월~일) 데이터 동기화 후 패턴 분석
- /sync 호출 시 자동 체크
- 수동 실행: POST /analyze 엔드포인트 제공
이유:
- 월요일에 지난 주 패턴을 한 번에 분석 (효율적)
- 사용자가 원할 때 즉시 분석 가능
- 자동화로 사용자 편의성 향상
3.3. 평일/주말 구분
고민: 평일/주말을 구분해야 할까?
초기 계획: 단순히 하나의 기본값만
문제점:
- 평일 07:00 기상, 주말 10:00 기상 → 패턴이 다름
- 알림 발송 시 부정확할 수 있음
결정: 평일/주말 구분
WEEKDAY_WAKE_TIME # 월~금 평균WEEKEND_WAKE_TIME # 토~일 평균
이유:
- 실제 사용 패턴 반영
- 더 정확한 Phase 계산
- 갱년기 여성의 경우 주말 늦잠이 흔함
4. 알림 기능 관련 결정
고민: 알림을 어떻게 구현할까?
문제점:
- 알림은 사용자가 앱을 열기 전에 발송
- 그때는 오늘 건강 데이터가 없을 수 있음
- 평일/주말 패턴이 다를 수 있음
초기 고민:
- 전날 데이터로 오늘 알림 발송?
- User Setting 기반으로 알림 발송?
최종 결정: 패턴 기반 Phase 계산 (알림 대응 가능)
- 이유:
- 알림은 앱 실행 전에 발송되므로 오늘 실시간 데이터 사용 불가
- 월요일에 계산된 평일/주말 평균 패턴으로 Phase 계산
- 패턴 기반이므로 알림 발송 시점에도 정확한 Phase 예측 가능
- 사용자가 앱을 열 때도 동일한 패턴으로 일관된 Phase 제공
향후 계획:
- 실시간 데이터 활용 여부는 테스트 후 결정
- 알림 기능 추가 시 패턴 기반 Phase로 발송 가능
5. 데이터 동기화 전략 결정
5.1. 동기화 시점
고민: 언제 데이터를 동기화할까?
옵션 1: 앱 실행 시마다
- 사용자가 앱을 열 때마다 오늘 데이터 동기화
옵션 2: 백그라운드 자동
- HealthKit Background Delivery
- Health Connect Background Sync
옵션 3: 하이브리드
- 앱 실행 시 + 백그라운드
결정: 옵션 1 (앱 실행 시)
- 이유:
- 구현 간단
- 배터리 효율적
- 사용자가 제어 가능
- Flutter 앱 개발 시 구현
향후 계획:
- Flutter 앱에서 HealthKit/Health Connect 연동
- 앱 실행 시 자동 동기화
- 백그라운드 동기화는 선택사항
5.2. 동기화 범위
고민: 얼마나 많은 데이터를 동기화할까?
옵션 1: 오늘만
- Phase 계산에 필요한 최소 데이터
옵션 2: 최근 7일
- 패턴 분석용
옵션 3: 전체 히스토리
- 모든 과거 데이터
결정: 오늘만 (기본) + 주간 동기화 (월요일)
- 평일(화~일): 앱 실행 시 오늘 데이터만
- 월요일: 지난 7일(월~일) 데이터 한 번에 동기화
- 이유:
- Phase 계산은 오늘 데이터만 필요
- 패턴 분석은 7일 데이터 필요
- 월요일에 한 번에 가져와서 분석 (효율적)
6. 테스트 전략 결정
고민: 어떻게 테스트할까?
문제점:
- Health Connect 데이터가 없음 (오늘 처음 사용)
- Flutter 앱 아직 없음
- 실제 데이터 수집 테스트 불가
결정: 단계별 접근
- 지금: 백엔드 API 로직 검증 (수동 데이터)
- 나중에: Flutter 앱 + 실제 건강 데이터
테스트 데이터:
- source_type: "manual"로 수동 입력
- Swagger UI에서 API 동작 확인
- Phase 계산 로직 검증
진짜 테스트:
- Flutter 앱 개발 후
- HealthKit/Health Connect 연동 후
- 실제 건강 데이터로 테스트
7. API 설계 결정
7.1. 엔드포인트 구조
최종 엔드포인트:
POST /api/service/user-phase/sync # 동기화 + Phase 반환 (월요일: 7일 동기화)
GET /api/service/user-phase/current # Phase 조회
GET /api/service/user-phase/settings # 설정 조회
PUT /api/service/user-phase/settings # 설정 업데이트
POST /api/service/user-phase/analyze # 패턴 분석 (수동 트리거)
GET /api/service/user-phase/pattern # 패턴 조회
설계 원칙:
- RESTful API 설계
- 명확한 엔드포인트 이름
- 인증 필수 (JWT)
- 일관된 응답 형식
- 월요일 자동 처리: /sync 호출 시 월요일이면 지난 7일 데이터 동기화 및 패턴 분석
7.2. Upsert 동작
결정: 같은 날짜면 업데이트
- 이유:
- 사용자가 하루에 여러 번 동기화 가능
- 최신 데이터로 업데이트
- 중복 데이터 방지
구현:
existing_log = db.query(HealthLog).filter(
HealthLog.USER_ID == user_id,
HealthLog.LOG_DATE == log_date
).first()
if existing_log:
# Updateelse:
# Insert
8. 최종 아키텍처
데이터 흐름
1. Flutter 앱 실행
↓
2. HealthKit/Health Connect에서 데이터 가져오기
- 평일(화~일): 오늘 데이터만
- 월요일: 지난 7일(월~일) 데이터
↓
3. POST /sync → 서버로 전송 (날짜별로 각각)
↓
4. TB_HEALTH_LOGS에 저장 (upsert)
↓
5. 월요일이면 주간 패턴 분석 자동 실행
↓
6. TB_USER_PATTERN_SETTINGS 업데이트 (평일/주말 평균)
↓
7. GET /current → Phase 조회
↓
8. 패턴 분석 결과 기준으로 Phase 계산
↓
9. 응답 반환 (current_phase, hours_since_wake 등)
Phase 계산 우선순위
패턴 분석 결과 (TB_USER_PATTERN_SETTINGS) - 최우선
- 평일: 평일 평균 기상 시간
- 주말: 주말 평균 기상 시간
↓ (없으면)
에러 (설정 필요 - 온보딩 또는 건강 데이터 동기화 허용)
9. 주요 트레이드오프
9.1. 실시간 데이터 vs 패턴 평균
선택: 패턴 평균 우선 (실시간은 나중에)
- 월요일 계산된 평일/주말 평균으로 Phase 계산
- 알림 발송에 적합 (앱 실행 전에도 Phase 예측 가능)
- 실시간 데이터 활용은 테스트 후 결정
- 일관된 Phase 제공으로 사용자 경험 향상
9.2. 확장성 vs 단순함
선택: 확장성 고려
- RAW_DATA JSON 필드 추가
- 나중에 다른 기능 개발 가능
- 지금 당장 사용 안 해도 구조 준비
9.3. 공평성 vs 기능
선택: 공평성 우선
- 체온 데이터 제외 (Android 미지원)
- iOS/Android 동일한 데이터 구조
- 기능 제한하더라도 공평성 유지
10. 핵심 설계 원칙
- 실시간 데이터 우선: 오늘 실제 데이터가 있으면 항상 사용
- Fallback 명확: 단계별 Fallback 전략으로 안정성 확보
- 확장 가능: RAW_DATA로 나중에 기능 추가 용이
- 공평성: iOS/Android 동일한 데이터 구조
- 사용자 중심: 갱년기 여성의 건강 모니터링에 특화
결론
User Phase Service는 실제 건강 데이터를 기반으로 정확한 Phase를 계산하고, 주간 패턴 분석으로 개인화된 서비스를 제공하는 것을 목표로 설계되었습니다.
주요 결정 사항:
- ✅ 통합 테이블 구조 (확장성)
- ✅ 평일/주말 구분 (정확성)
- ✅ 3단계 Fallback (안정성)
- ✅ 공통 데이터만 사용 (공평성)
- ✅ 하이브리드 패턴 분석 (자동화 + 수동)
이러한 설계 결정을 통해 확장 가능하고 정확하며 사용자 친화적인 서비스를 구현할 수 있었습니다.
'AI 개발' 카테고리의 다른 글
| 사용자 패턴 분석 설계 결정 사항 (0) | 2025.12.08 |
|---|---|
| GPT-4o-mini가 복잡한 JSON 시나리오 생성에 실패했던 이유와 해결 방법 (실전 트러블슈팅) (0) | 2025.12.03 |
| [Dev Log] LLM으로 '무한 시나리오 게임' 만들기: 기획부터 JSON 생성까지 자동화 파이프라인 (0) | 2025.12.02 |
| 마음봄 프로젝트 - 감정 분석 RAG 모델 (1) | 2025.12.02 |
| [Tech Log] 단순 챗봇을 넘어 'AI 에이전트'로: 멘탈케어 서비스 '마음봄' 아키텍처 설계기 (0) | 2025.12.02 |