과거 날짜 위치 복원 + 과거 날씨(ASOS) 연동, 리캡/일기 알림·코인 보상까지: “기록 경험”을 완성하는 흐름 만들기
오늘 작업은 기능을 몇 개 추가한 수준이 아니라,
과거 기록을 “그날의 컨텍스트(위치/날씨)”로 복원하고,
생성 완료 후 알림과 보상(코인) 으로 사용자 경험을 닫는(Closing) 작업이었다.
(Front: 위치 전송 분기/타임아웃/알림 라우팅, Back: 위치 복원/ASOS/서비스 분리/알림/코인)
AI 일기/미리보기는 사용자가 과거 날짜를 선택해도, 클라이언트가 현재 GPS를 그대로 전송하면서 과거 기록에 현재 위치가 덮이는 문제가 발생할 수 있다.
또한 그날의 날씨는 실시간 예보가 아니라 과거 기상 기록(ASOS) 을 써야 컨텍스트가 맞는다.
따라서 오늘 목표는 다음 두 가지였다.
DiaryUploadPage.tsx)핵심은 “과거 날짜이면 클라이언트 GPS를 보내지 않고”,
백엔드가 DB 기준으로 위치를 찾아 반영할 수 있도록 요청 모델을 분기한 것이다.
isPastDate 플래그로 조건부 위치 전송사용자가 선택한 날짜가 과거인지 여부에 따라, 프론트에서 최종 위치를 결정하는 로직을 추가했다.
latitude, longitude를 우선 사용finalLocationCoords, finalLocationName로 UI 반영 기준을 단일화결과적으로 UI는 “오늘은 GPS”, “과거는 DB 복원”이라는 정책이 명확해지고,
화면/지도/날씨 로직이 한 기준으로 움직이게 된다.



http-client.ts)AI 일기 생성, 리캡 생성 등은 요청 시간이 길 수 있어 기본 10초 타임아웃에서 끊기는 문제가 있었다.
ECONNABORTED 같은 타임아웃 에러 방지날짜 분기와 좌표 적용은 오류가 나면 체감이 큰 영역이라, 판단 근거를 로그로 남겼다.
DiaryServiceImpl)백엔드에서 “과거 날짜”일 경우 위치 우선순위를 명확히 정의했다.
AiDiaryResponse에 포함해 프론트 UI가 즉시 갱신 가능
ExternalApiService)날씨는 “날짜”에 따라 호출 API가 달라야 한다.
getWeatherInfo에서 날짜 기준으로 자동 분기:이 방식은 “사진 기반 추정”보다 신뢰성이 높고,
과거 기록을 ‘그날의 날씨’로 맞출 수 있다는 점에서 데이터 품질이 상승한다.
LocationServiceImpl)과거 위치 복원이 “일회성”이면 재사용 가치가 낮다.
그래서 일기 저장 시 해당 날짜/장소를 walk_routes에 기록하도록 보강해,
같은 날짜에 추가 일기를 작성할 때 동일 위치를 공유할 수 있게 했다.
DiaryServiceImpl에 집중되어 있던 비대한 로직을 관심사별로 분리하고,
상위에서 흐름만 제어하는 오케스트레이터 패턴으로 구조를 정리했다.
DiaryAiService: AI 분석/프롬프트 실행DiaryVectorService: Milvus 동기화/비동기 저장DiaryMediaService: 이미지 업로드(Archive) + MongoDB 메타데이터ExternalApiService: Kakao 주소 변환 + 날씨 API 분기효과: 변경이 자주 생기는 영역(외부 API, AI, 미디어)을 분리해서
추후 유지보수와 테스트 작성 난이도를 낮추는 방향으로 정리했다.
createNotification API 함수 추가 및 요청 DTO 정의DIARY 타입 알림 전송 (DiaryStylePage, AiDiaryPage)DIARY → /diary/{targetId}RECAP → /recap/{targetId}핵심은 “알림이 와도 사용자가 어디로 가야 하는지”가 명확해야 한다는 점이었다.
캘린더 같은 우회 경로 대신 상세 페이지로 바로 이동하도록 정리했다.

NotificationClient(Feign)로 유저 서비스 알림 API 호출RecapServiceImpl.createAiRecap()에서 자동/수동 생성 모두 알림 지원

사용자 행동을 “완료 경험”으로 만드는 방법 중 하나가 보상 체계다.
리캡 생성은 사용자 입장에서 비용이 큰 행동(기억/정리/회고)이므로 일기보다 보상을 높게 설정했다.
UserClient(Feign)로 유저 서비스 earnCoin 호출coin: 30L)하여 사용자에게 즉시 피드백 제공
/diary/:id, /recap/:id) 확인오늘 작업에서 가장 크게 느낀 점은 “과거 기록” 기능은 단순히 날짜만 바꾸는 게 아니라, 그날의 컨텍스트(위치/날씨)까지 같이 복원되어야 완성된 경험이 된다는 것이었다. 프론트에서 과거 날짜에 GPS를 보내지 않도록 정책을 분기한 것은 작은 변경처럼 보이지만, 데이터 오염을 막는 핵심 안전장치가 됐다. 백엔드에서 DB 위치를 최우선으로 사용하고 폴백을 두면서, “정확성”과 “사용자 경험” 사이의 균형을 실제로 설계해볼 수 있었다. 특히 날씨는 실시간 예보와 과거 기록(ASOS)을 분기해야 한다는 점에서, 시간 개념이 들어간 외부 API 설계가 생각보다 복잡하다는 걸 배웠다. 서비스 분리(오케스트레이터 패턴) 과정에서는 기능이 늘어날수록 한 클래스에 쌓이는 로직이 유지보수성을 빠르게 무너뜨린다는 걸 체감했고, 책임을 나누는 것 자체가 리팩토링의 핵심임을 다시 확인했다. 알림 연동은 “기능 완료 후 사용자에게 닫아주는 경험”을 만드는 작업이었고, 클릭 라우팅을 직접 상세로 연결하니 알림의 가치가 올라갔다. 코인 보상은 단순한 포인트 지급이 아니라, 사용자의 행동을 서비스 흐름에 정착시키는 장치라는 점을 배우게 됐다. 동시에 알림/코인처럼 외부 서비스에 의존하는 기능은 실패해도 본 트랜잭션을 망치지 않도록 설계해야 한다는 원칙을 다시 적용했다. 전역 타임아웃을 60초로 올리면서 “긴 작업”을 다루는 서비스는 네트워크 정책도 제품의 일부라는 걸 느꼈다. 전체적으로는 기능 하나를 붙이는 것보다, 데이터 정합성·예외 처리·UX 피드백 루프를 함께 닫는 게 더 중요한 작업이라는 걸 경험한 하루였다.