[FE-10] 채팅방 실시간 화면 재작성 (송수신·읽음·타이핑·재연결·게스트 방출)

작업 내용 (설계 의도)

변경 사항

근거: 설계 문서 S2. 파일: app/rooms/[id].tsx(재작성, 이 티켓 단독 소유).

기존 REST 폴링 방 화면을 실시간으로 재작성한다. useChatSocket(FE-06)으로 송수신·타이핑·읽음, 재연결/백필, 게스트 방출 처리. 테마 토큰 적용.

  • 컨테이너: useMessages(기존, 초기 로드) + useChatSocket(실시간) + useMarkRead(FE-05) + useMyProfile(내 userId, 말풍선 정렬·읽음 계산).
  • 프레젠테이션(FE-04 기반): MessageBubble(내/상대 말풍선 색 대비, 읽음 표시, 시각), TypingIndicator(상대 입력 중, 3초 TTL useState), MessageComposer(단일 입력 CTA — 읽기전용 게스트면 비활성+안내), ConnectionBanner(재연결/폴링 폴백), GuestExpiryBanner(본인 게스트 만료 D-day).
  • 4상태 + 특수: loading(스켈레톤), empty(“첫 메시지를 보내보세요”), error(메시지 로드 실패 ErrorView; 소켓 실패는 배너로 별도, 화면은 REST로 동작), success(실시간 append). 게스트 방출(REST/소켓 403) → 전체화면 “참여 기간이 만료되어…” + “목록으로”.
  • 방 진입 시 마지막 메시지 read 처리(markRead), 새 수신 시 화면 포커스면 read 갱신.
  • 방장이면 헤더에 게스트 초대 진입(app/invite/[roomId]).
  • 토스 패턴: 한 화면 한 과업, 하단 단일 입력 CTA, 말풍선 accent 1곳.

롤백: chat.realtime.enabled OFF면 소켓 없이 기존 REST 폴링 동작(FE-06 폴백).

의존

  • FE-04 (UI 프리미티브), FE-05 (markRead), FE-06 (소켓 훅)

다이어그램

처리 흐름

sequenceDiagram
    participant User
    participant Screen as rooms/[id]
    participant Socket as useChatSocket
    participant Cache
    User->>Screen: 방 진입
    Screen->>Socket: subscribe(roomId)
    Screen->>Screen: markRead(last)
    User->>Screen: 입력 중
    Screen->>Socket: sendTyping
    User->>Screen: 전송
    Screen->>Socket: send(content)
    Socket-->>Cache: append(ChatMessage)
    Cache-->>Screen: 리렌더

테스트 케이스

  • 내 메시지는 우측, 상대 메시지는 좌측 정렬로 렌더된다
  • 실시간 수신 메시지가 리스트에 append되어 표시된다
  • 상대 타이핑 이벤트 수신 시 인디케이터가 표시되고 수 초 후 사라진다
  • 읽기 전용 게스트는 입력창이 비활성이고 안내가 표시된다
  • 게스트 방출(403) 시 만료 안내 전체화면과 “목록으로”가 렌더된다
  • 연결 끊김 시 재연결 배너가 표시되고 폴링 폴백으로 메시지가 계속 갱신된다
  • 방 진입 시 markRead가 호출되어 해당 방 안읽은 수가 0이 된다