[feat] 대화 저장 및 조회 API 구현#11
Conversation
서비스상 하루의 시작 시각(기본 06:00)은 conversation.day-start-time 설정으로 관리
Test Coverage
|
theminjunchoi
left a comment
There was a problem hiding this comment.
좋은데요?
아래 질문하나 남겼습니다!
approve는 해둘게요!
| @LastModifiedDate | ||
| @Column(name = "updated_at", nullable = false) | ||
| var updatedAt: Instant = Instant.now() | ||
| protected set |
There was a problem hiding this comment.
궁금한 게 있습니다!
사실 Conversation 엔티티는 생성 후 절대 수정하지 않아서 udpatedAt이 죽은 필드/컬럼이 될 것 같은데, 만든 이유가 있을까요??
There was a problem hiding this comment.
Conversation 은 대화방이고 사용자가 남기는 메시지나 감정봇들이 다는 댓글은 모두 Message에 저장됩니다.
추후 해당 방의 입력이 몇 분 전에 입력된 것인지 보여줄 것을 생각하여 updatedAt을 넣어봤습니다!
There was a problem hiding this comment.
해당 방의 마지막 입력이 몇 분 전인지는 마지막 메시지의 created_at을 보면 되지 않을까요...?
LastModifiedDate는 conversation 행 자체가 수정될 때만 갱신되는데, 사용자든 감정봇이든 메시지는 전부 Message에 INSERT라 conversation 행은 안 건드리니까, updatedAt이 갱신될 일이 없는 것 같아서요!
혹시 제가 잘못 이해한거라면 알려주세요!
There was a problem hiding this comment.
말씀하신대로네요! 지금대로라면 conversation의 updatedAt은 죽은 컬럼입니다...
해결을 위해 방안 두 가지를 검토봤는데요,
- 메시지 저장 시마다 conversation.updatedAt을 함께 갱신
- 목록 조회 시 방마다 마지막 메시지를 조회해서 시간 표시
2안은 조회할 때마다 window function 이나 서브쿼리로 방마다 최신 메시지를 골라야 해서, 상대적으로 자주 호출되는 조회 쿼리가 무거워집니다. 반면 1안은 메시지 저장 시 UPDATE 한 번 추가되는 정도라 비용이 훨씬 작아서 1안으로 작업해봤습니다.
다만 저장 지점이 늘어날 때마다 updatedAt 갱신을 빠뜨릴 위험이 있어서, Conversation.createMessage()로 메시지 생성 시 conversation의 updatedAt을 갱신하도록 했습니다. 이렇게 연관 엔티티의 정합성을 루트 엔티티가 책임지는 걸 DDD에서 Aggregate Root라고 부르더라구요. 이번 상황에 맞는 것 같아 적용해봤습니다!
메시지 저장 지점마다 갱신을 빠뜨릴 위험이 있어, Conversation.createMessage()로 메시지 생성 통로를 일원화해 생성과 동시에 updatedAt이 갱신되도록 구현
|
Caution Review failedAn error occurred during the review process. Please try again later. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔗 연관 이슈
📌 개요
사용자의 감정 기록(대화)을 DB에 저장하고 조회하는 기능을 구현했습니다. 채팅방(
Conversation)과 말풍선(Message)을 분리해 저장하며, 이후 이슈 #4(LLM 댓글 생성)에서 캐릭터 메시지 또한Message에 저장할 예정입니다.🔧 주요 변경사항
도메인 · 스키마 (V2 마이그레이션)
Conversation— 채팅방.memberId(ID 참조) · 생성/수정 시각만 보유Message— 말풍선.senderType(USER/CHARACTER) +emotionType(캐릭터일 때만, 6종) 분리로 발신 주체와 감정을 표현repliesToMessageId자기참조로 표현 (nullable)CHARACTER ⟺ emotionType 존재를init에서 강제EmotionType— 감정 캐릭터 6종(기쁨·분노·불안·까칠·다정·엉뚱),emotion패키지에 정의저장·조회 서비스
conversationId없으면 새 채팅방 생성, 있으면 토큰을 통한 사용자 검증 후 이어서 저장(본인 소유 채팅방에만 대화 가능)conversation.day-start-time설정값으로 조정 가능 (@ConfigurationProperties)API 3종 (모두 로그인 필요)
POST /api/conversations/messages— 저장 (응답에conversationId포함 → 이후 클라 요청 시 conversationId 포함하여 요청)GET /api/conversations?date=— 날짜별 채팅방 목록GET /api/conversations/{id}/messages— 채팅방 메시지 전체 (id 오름차순)공통 개선
ErrorCode추가:CONVERSATION_NOT_FOUND(404) ·CONVERSATION_ACCESS_DENIED(403)GlobalExceptionHandler에 쿼리 파라미터 누락·형식 오류 핸들러 추가 — 기존엔date=abc같은 요청이 500으로 떨어졌음 → 400INVALID_INPUT🌐 API · DB 영향
V2__conversation.sql—conversations·messages테이블 생성 (기존 테이블 불변)💬 리뷰 포인트
1. 날짜 경계 로직 — 날짜별 조회의 "하루"는 KST 06:00 ~ 익일 06:00입니다. 요청받은 날짜(KST 기준)를 내부에서 UTC Instant 범위로 변환해 조회하며, DB 저장(created_at)도 UTC입니다. 단위 테스트로 경계 변환을(
2026-07-19→07-18T21:00Z ~ 07-19T21:00Z), 통합 테스트로 새벽 2시(KST)에 만든 방이 전날 목록에만 나오는 것을 확인했습니다.2. 채팅방/메시지 관련 기능에서 토큰을 이용한 유저 검증 —
AuthPrincipal.memberId와 채팅방 주인을 비교합니다(불일치 시 403).3.
messages.content가 VARCHAR(500)인 이유 — 사용자 입력은 140자 제한(DTO 검증)이지만, 같은 테이블에 이후 LLM 캐릭터 메시지(#4)가 들어오므로 컬럼은 여유 있게 잡았습니다.4. 날짜별 목록은 방 "생성일" 기준 — 자동 종료(새벽 6시)가 아직 없어 어제 만든 방에 오늘 이어 쓸 수 있는데, 이 방은 어제 목록에만 나옵니다. 종료 기능이 들어올 때 자연스럽게 정리될 부분이라 이번 범위에선 그대로 뒀습니다.
5. 이슈와 관련없는 작업 분리 — 추후 채팅방 종료 후 카드 생성기능이나, 채팅방 삭제와 같은 기능에 필요한 컬럼들이 있겠지만, 관련 이슈에서 작업하는게 맞다고 생각해 우선 작업하지 않았습니다. 테이블 생성 시 부터 미리 작업해두는게 좋다고 생각되면 말씀해주세요!