한마디로
감정 기록과 AI 분석을 제공하는 Zero Gravity의 Spring Boot REST API입니다. 프리티어 클라우드 위에 인프라부터 배포까지 직접 구축하고, 비용 제약 안에서 AI 기능을 설계했습니다.
- 5개 도메인, 15개 엔드포인트 — 인증, 감정 기록, 통계, AI 분석을 하나의 API로 설계했습니다.
- OCI + Terraform 6 모듈로 인프라를 직접 구축하고, Build-first 전략으로 Zero-Downtime 배포를 구현했습니다.
- Time Bucket 샘플링으로 Gemini API 전송량을 97% 절감하여, AI 기능을 비용 한도 내에서 운영했습니다.
팀 프로젝트에서 프로덕션까지.
팀 프로젝트로 시작한 Spring Boot 백엔드를 프로덕션 서비스로 전환했습니다. 기본 CRUD API만 존재했던 프로젝트에 인증, 인프라, 배포 파이프라인을 구축하고 AI 분석 기능을 추가했습니다.
- 레이어드 아키텍처를 도메인별 구조로 재구성했습니다.
- NextAuth OAuth → JWT 인증 체계를 구현했습니다.
- OCI 위에 인프라를 직접 구축하고 Zero-Downtime 배포를 구현했습니다.
- Gemini API 기반 감정 분석 기능을 추가했습니다.
API Endpoints
Infrastructure
전부 보내면 한 달도 못 버팁니다.
Gemini API로 감정 기록을 분석하는 기능을 구현하려 했습니다. 1년치 기록을 전부 보내면 요청당 Input 토큰이 ~55K에 달했습니다. 프로젝트 예산으로는 감당할 수 없었습니다.
데이터를 줄이면 분석 품질이 떨어지고, 기능 자체를 포기하기엔 핵심 기능이었습니다.
이미 있는 데이터에서 답을 찾았습니다.
전체를 보낼 수 없다면, 각 기간을 대표하는 기록만 골라서 보내면 됐습니다. 문제는 "대표"를 어떤 기준으로 고를 것인가였습니다.
차트 API의 기간별 평균 레벨과 버킷별 최빈 이유를 샘플링 기준으로 사용했습니다. "이 달의 평균 레벨에 가장 가깝고, 최빈 이유를 포함하는" 기록 1건을 각 버킷에서 선별했습니다.
버킷 하나, 대표 기록 하나.
기간을 균등한 시간 단위(버킷)로 나누고, 각 버킷에서 가장 대표적인 기록 1개를 선택했습니다. 상위 12개를 그냥 뽑으면 특정 달에 집중될 수 있기 때문에, 버킷 단위로 균등하게 나눴습니다.
감정 레벨 60% + 이유 매칭 40%의 가중 스코어로 각 버킷의 대표 기록을 선별했습니다. Daily 기록은 하루 전체를 돌아보며 쓴 기록이므로 1.5배 가중치를 적용했습니다.
동점이면 일기가 긴 순, 이유가 많은 순, 최신 순으로 타이브레이크했습니다.
예시: Year 분석의 1월 버킷 (평균 감정 레벨: 4.5, 최빈 이유: "Work")
AI 분석 결과는 24시간 캐싱하고, 감정 기록이 변경되면 해당 기간 캐시를 무효화했습니다.
전송량 97% 절감, 요청당 $0.002
제약이 전략을 만들었습니다. 기능을 포기하는 대신, 이미 존재하는 데이터를 새로운 맥락에서 재활용하는 발상으로 문제를 해결했습니다.