[FE-05] 채팅 REST 엔드포인트 + Query 훅 (unread/read/backfill/goods-chat)
작업 내용 (설계 의도)
변경 사항
근거: 20260704-채팅시스템고도화-design-fe-app.md “API 연동 표”·BE TDD “REST API 계약”.
채팅 관련 신규 REST 엔드포인트 함수와 TanStack Query 훅을 추가한다. 신규 파일 api/chat.ts·lib/useChat.ts. 기존 api/room.ts·lib/useRooms.ts는 재사용(방목록·메시지·전송은 기존 훅 유지). 컴포넌트는 api/를 직접 호출하지 않고 훅 경유.
api/chat.ts:getUnreadCounts()(GET /rooms/me/unread),markRead(roomId, lastReadMessageId)(POST /rooms/{roomId}/read),backfillMessages(roomId, afterMessageId)(GET /rooms/{roomId}/messages/backfill),startGoodsChat(productId)(POST /products/{productId}/chat),evictGuest(roomId, userId)(POST /rooms/{roomId}/guests/{userId}/evict).lib/useChat.ts:useUnreadCounts,useMarkRead(성공 시 해당 방 unread 캐시 0 갱신),useBackfill,useStartGoodsChat,useEvictGuest.- 안읽은 수 낙관적 갱신: 실시간 수신 시 방별 +1(내가 보낸 것 제외)은 FE-06 소켓 훅에서
setQueryData로 처리하고, 이 티켓은 서버 SSOT 조회/재동기화 담당.
1·2단계 경계: getUnreadCounts/markRead는 1단계(FR-7/9 P0). backfillMessages(FR-10 재연결 backfill)·startGoodsChat(FR-18 goods)·evictGuest(FR-15 수동 방출)는 2단계 기능이며 각각 chat.realtime.enabled(backfill)·chat.goods.enabled(goods)·chat.community.enabled(evict) 플래그로 게이팅된다(플래그 정의는 FE-15 feature-flags.ts). 함수·훅은 1단계에 함께 정의하되 호출부(FE-06/FE-10/FE-14)가 플래그로 노출을 제어한다.
필드는 BE 계약과 일치(RoomUnreadResponse{roomId,unreadCount} 등). getBeClient() 경유(Authorization Bearer 자동).
의존
- FE-02 (chat-types)
다이어그램
처리 흐름
sequenceDiagram participant Screen participant Hook as useMarkRead participant Api as api/chat.ts participant BE Screen->>Hook: markRead(roomId, msgId) Hook->>Api: POST /rooms/{id}/read Api->>BE: {lastReadMessageId} BE-->>Api: UnreadResponse Hook->>Hook: setQueryData(unread → 0)
테스트 케이스
useUnreadCounts가RoomUnreadResponse[]를 방별 매핑으로 반환한다useMarkRead성공 후 해당 방의 unread 캐시가 0으로 갱신된다markRead실패 시 예외를 전파하되 화면을 막지 않는다(비차단)useStartGoodsChat가RoomResponse를 반환하고 기존 방이 있으면 같은 roomId를 받는다backfillMessages가afterMessageId이후 메시지만 반환한다(경계값)