Skip to content

OpenAI API 호출량 최적화 변경점 공유 (통계 데이터 관리) #175

@kisusu115

Description

@kisusu115

연관 이슈

#74

목적

  • OpenAI API 호출량 최적화 진행 중 변경점 공유
  • 주요 엔드포인트 변경 의도 및 데이터 흐름 설명
    • GET /{elderId}/health-analysis - 날짜별 건강 징후 데이터 조회
    • GET /{elderId}/home - 홈 화면 데이터 조회
    • GET /{elderId}/weekly-stats - 주간 통계 데이터 조회
  • 설계/엔티티 구조 논의용 이슈
  • 중간 공유가 필요할 것 같아 작성한 이슈입니다.
  • 의문점이나 논의점에 대해 자유롭게 의견 달아주시면 감사하겠습니다!

논의 포인트

  • Daily / Weekly 통계 구조가 현재 데이터 플로우에 적합한가?

작업 상세 내용

응답에 필요한 데이터 및 AI 분석 결과는 /call-data 처리 시 저장

  • 날짜별 건강 징후 데이터 조회에 포함되는, analysisComment(from AI)는 CareCallRecord에 포함
  • 홈 화면 데이터 조회의 해당 날짜에 대한 분석 데이터는 DailyStatistics 테이블로 유지
    • 특정 일에 대한 분석이 "홈 화면"에 의존할 필요 없다고 생각하여, 데이터를 독립적으로 유지하되 홈 화면에 대한 응답은 DTO 구성하여 응답하도록 설정
    • DailyStatistics는 elder&date 에 대해 하나만 존재(unique), upsert 방식으로 유지
    • 다음 복약 예정 시간에 해당하는 nextTime의 경우 통계 데이터에 적합하지 않다고 판단, 이 값만 클라이언트 조회 요청 시 계산 후 주입
  • 주간 통계 데이터 조회의 해당 주간에 대한 분석 데이터는 WeeklyStatistics 테이블로 유지
    • WeeklyStatistics는 elder&startDate(월요일) 에 대해 하나만 존재(unique), upsert 방식으로 유지
  • 추후 캐싱 도입 검토

예상(현재 진행중인) Entity 구조

DailyStatistics

@Entity
@Table(name = "daily_statistics")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DailyStatistics {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "elder_id", nullable = false)
    private Elder elder;

    @Column(nullable = false)
    private LocalDate date;

    // 식사 여부
    // TODO: Embedded Type 전환 고려 - MealStatus 내부 Boolean 필드 3가지
    private Boolean breakfastTaken;
    private Boolean lunchTaken;
    private Boolean dinnerTaken;

    // 복약 요약
    private Integer medicationTotalTaken;
    private Integer medicationTotalGoal;

    // 약물별 복약 상세 정보
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(columnDefinition = "json")
    private List<MedicationInfo> medicationList;

    // 평균 수면 시간(분) & 평균 혈당
    private Integer avgSleepMinutes;
    private Integer avgBloodSugar;

    // 상태 및 요약
    @Column(columnDefinition = "TEXT")
    private String aiSummary;

    // TODO: Enum 변환 고려
    private String healthStatus; // "좋음", "나쁨"
    private String mentalStatus; // "좋음", "나쁨"

    @Getter
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class MedicationInfo {
        private String type;
        private Integer taken;
        private Integer goal;
        private List<DoseStatus> doseStatusList;
    }

    @Getter
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class DoseStatus {
        private MedicationScheduleTime time;
        private Boolean taken;
    }

WeeklyStatistics

@Entity
@Table(name = "weekly_statistics")
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class WeeklyStatistics {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "elder_id", nullable = false)
    private Elder elder;

    @Column(nullable = false)
    private LocalDate startDate;

    @Column(nullable = false)
    private LocalDate endDate;

    // 요약 통계
    // TODO: Embedded Type 전환 고려 - SummaryStats
    private Integer mealRate;
    private Integer medicationRate;
    private Integer healthSignals;
    private Integer missedCalls;

    // 식사 횟수
    // TODO: Embedded Type 전환 고려 - MealStats
    private Integer breakfastCount;
    private Integer lunchCount;
    private Integer dinnerCount;

    // 약물별 통계
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(columnDefinition = "json")
    private Map<String, MedicationStats> medicationStats;

    // 심리 상태 통계
    // TODO: Embedded Type 전환 고려 - PsychSummary
    private Integer psychGoodCount;
    private Integer psychNormalCount;
    private Integer psychBadCount;

    // 혈당 상태 통계
    @JdbcTypeCode(SqlTypes.JSON)
    @Column(columnDefinition = "json")
    private BloodSugarStats bloodSugarStats;

    // 평균 수면 시간
    // TODO: Embedded Type 전환 고려 - AverageSleep
    private Integer avgSleepHours;
    private Integer avgSleepMinutes;

    // AI가 생성한 건강 상태 요약 문장
    @Column(columnDefinition = "TEXT")
    private String aiHealthSummary;

    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class MedicationStats {
        private Integer totalCount;
        private Integer takenCount;
    }

    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class BloodSugarStats {
        private BloodSugarType beforeMeal;
        private BloodSugarType afterMeal;
    }

    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public static class BloodSugarType {
        private Integer normal;
        private Integer high;
        private Integer low;
    }

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions