feat(chat): 채팅방 리스트 조회 API를 추가한다

This commit is contained in:
2026-05-14 16:12:14 +09:00
parent 3a2c21c896
commit acd0393a0e
8 changed files with 650 additions and 2 deletions

View File

@@ -20,6 +20,9 @@
- 메시지 발송 시 상대방이 해당 방에 입장해 있으면 푸시를 보내지 않고 실시간으로 메시지를 표시한다.
- 메시지 발송 시 상대방이 해당 방에 입장해 있지 않으면 푸시 알림을 발송한다.
- 기존 AI 채팅 도메인의 엔티티라도 재활용할 수 있는지 코드 근거에 따라 결정한다.
- 사용자가 참여 중인 AI 채팅방과 DM 채팅방을 하나의 채팅 리스트 API에서 조회할 수 있게 한다.
- 채팅 리스트는 전체, AI 채팅, DM 채팅 필터를 지원한다.
- 채팅 리스트 응답은 방 입장에 필요한 `roomId`, 상대방 표시 정보, 마지막 메시지 요약, 최종 대화 시간을 제공한다.
---
@@ -30,6 +33,7 @@
- 텍스트/음성 외 이미지, 파일, 이모티콘, 읽음 확인, 메시지 수정 기능은 이번 범위에 포함하지 않는다.
- typing indicator는 이번 범위에 포함하지 않는다.
- 관리자 화면 개편은 이번 범위에 포함하지 않는다.
- 채팅 리스트 API에서 메시지 본문 전체, 읽지 않은 메시지 수, 고정/숨김/삭제 상태, 검색 기능은 이번 범위에 포함하지 않는다.
---
@@ -46,6 +50,9 @@
- 크리에이터는 방에 들어와 있지 않을 때 새 메시지가 오면 푸시로 알림을 받고 싶다.
- 크리에이터는 방에 들어와 있을 때 새 메시지가 오면 푸시 없이 화면에 바로 표시되기를 원한다.
- 양쪽 사용자는 상대방이 방에 들어와 있을 때 새 메시지를 즉시 확인하고 싶다.
- 사용자는 내가 참여 중인 모든 채팅방을 최신 대화순으로 보고 싶다.
- 사용자는 AI 채팅방만 또는 DM 채팅방만 필터링해서 보고 싶다.
- 사용자는 리스트에서 상대방 닉네임, 프로필 이미지, 마지막 대화 요약, 최종 대화 시간을 확인한 뒤 방에 입장하고 싶다.
---
@@ -111,6 +118,26 @@
- 한 사용자가 여러 기기에서 같은 방에 입장할 수 있다면, 하나 이상의 활성 연결이 있을 때 입장 중으로 판단한다.
- 앱 백그라운드 전환 또는 화면 이탈 이벤트가 서버에 도달하지 못해도 SSE 연결 종료와 Redis TTL 만료로 방 입장 상태가 해제되어야 한다.
### 채팅 리스트 API
#### Requirements
- 인증된 회원이 참여 중인 채팅방만 조회한다.
- 필터는 `ALL`, `AI`, `DM` 3가지를 지원한다.
- `AI`는 기존 AI 캐릭터 채팅방을 의미한다.
- `DM`은 유저-크리에이터 채팅방을 의미하며, API 문서와 클라이언트 표시 용어에서 User-Creator 채팅 대신 DM으로 명명한다.
- 기본 정렬은 최종 대화 시간 내림차순이다.
- 채팅 리스트는 최신순 30개씩 조회하고 cursor 기반으로 다음 페이지를 조회한다.
- 응답 항목은 방 입장을 위한 `roomId`, `chatType`, 상대방 닉네임, 상대방 프로필 이미지, 마지막 대화 요약, 최종 대화 시간을 포함한다.
- 마지막 대화 요약은 서버에서 15글자까지 내려주고, 15글자를 초과하면 말줄임표를 붙인다.
- 최종 대화 시간은 UTC 기준 값을 내려주고, 클라이언트가 표시 방식과 로컬 타임존 변환을 처리한다.
- 마지막 메시지가 없는 방은 채팅 리스트에 노출하지 않는다.
#### Edge Cases
- 상대방 회원 또는 AI 캐릭터의 프로필 이미지가 없으면 기본 이미지를 사용한다.
- 마지막 메시지가 음성 메시지이면 본문 요약 대신 `[음성 메시지]`를 내려준다.
- 마지막 메시지가 비활성화되었거나 표시할 수 없는 상태라면 해당 메시지를 제외하고 다음 최신 표시 가능 메시지를 기준으로 요약한다.
- DM 채팅방에서 현재 회원이 유저인지 크리에이터인지와 관계없이 상대방은 나를 제외한 참여자로 계산한다.
---
## 8. Technical Constraints
@@ -147,6 +174,24 @@
- 단점: 신규 엔티티, 저장소, 실시간 연결 관리, API가 필요해 초기 구현량이 늘어난다.
- 판단: 이번 요구사항의 권장안이다.
### 채팅 리스트 API 접근안
#### Option A: AI/DM 리스트 API를 각각 작성
- 장점: 각 도메인의 조회 조건과 응답 조립을 단순하게 유지할 수 있다.
- 단점: 클라이언트가 전체 리스트를 만들기 위해 두 API를 호출하고 병합/정렬해야 한다.
- 판단: 전체 필터 요구사항과 맞지 않아 권장하지 않는다.
#### Option B: 통합 리스트 API에서 필터로 구분
- 장점: 클라이언트는 하나의 API로 전체, AI, DM 탭을 처리할 수 있다.
- 장점: 참여 중인 방만 노출, 최신 대화순 정렬, 마지막 메시지 요약 정책을 서버에서 일관되게 적용할 수 있다.
- 단점: 서버에서 AI 채팅방과 DM 채팅방의 응답 모델을 하나로 맞추는 조립 계층이 필요하다.
- 판단: 이번 채팅 리스트 API의 채택안이다.
#### Option C: 기존 AI 채팅 리스트 API에 DM을 추가
- 장점: 새 endpoint 수를 줄일 수 있다.
- 단점: 기존 AI 채팅 API의 의미가 넓어지고, DM 도메인 결합이 생긴다.
- 판단: 공개 API 의미가 불명확해지므로 권장하지 않는다.
---
## 10. Metrics
@@ -158,5 +203,12 @@
---
## 11. Open Questions
- 없음. URL prefix와 DTO 필드명은 구현 직전 추천안을 제시해 확정하고, SSE 인증과 재연결 간격은 본 문서의 Technical Constraints 기준을 따른다.
## 11. Confirmed Defaults
- 채팅 리스트에서 마지막 메시지가 없는 방은 노출하지 않는다.
- 음성 메시지의 마지막 대화 요약 문구는 `[음성 메시지]`를 사용한다.
- 채팅 리스트 API URL prefix는 `/api/v2/chat/rooms`를 사용한다.
- 채팅 리스트 DTO 필드명은 `roomId`, `chatType`, `targetName`, `targetImageUrl`, `lastMessage`, `lastMessageAt`을 사용한다.
- `targetName`은 AI 채팅이면 캐릭터명, DM이면 나를 제외한 참여 회원 닉네임이다.
- `targetImageUrl`은 AI 채팅이면 캐릭터 대표 이미지, DM이면 나를 제외한 참여 회원 프로필 이미지이며, 이미지가 없으면 기본 이미지 URL을 내려준다.
- 채팅 리스트는 최신순 30개씩 cursor 기반으로 페이징한다.
- SSE 인증과 재연결 간격은 본 문서의 Technical Constraints 기준을 따른다.