Skip to content

[FEAT] 실시간 채팅 UI 구현 및 품질 개선#11

Merged
ydking0911 merged 10 commits intomainfrom
feat/#10/실시간-채팅-ui-구현
Apr 2, 2026

Hidden character warning

The head ref may contain hidden characters: "feat/#10/\uc2e4\uc2dc\uac04-\ucc44\ud305-ui-\uad6c\ud604"
Merged

[FEAT] 실시간 채팅 UI 구현 및 품질 개선#11
ydking0911 merged 10 commits intomainfrom
feat/#10/실시간-채팅-ui-구현

Conversation

@ydking0911
Copy link
Copy Markdown
Contributor

개요

백엔드 MySQL 기반 채팅 시스템 전환에 맞춰 채팅 UI 전체를 재구현. STOMP WebSocket 기반 실시간 메시지 송수신, 그룹/1:1 채팅 분기, 채팅방 정보 패널(멤버 목록), SSE 알림 연동까지 구현.


구현 기능

1. 채팅 상태 관리 — Zustand chatStore

채팅방 목록, 메시지 페이지네이션 상태, 읽음 카운트를 Zustand 스토어로 중앙 관리합니다. chatRoomsmessages를 분리 저장하고, 컴포넌트 간 상태 공유와 SSE 알림으로 인한 카운트 갱신 모두 스토어를 통해 처리

chatStore
  ├── chatRooms[]             — 채팅방 목록 + unreadCount
  ├── messages[chatRoomNo][]  — 메시지 페이지네이션 (커서 기반)
  ├── setChatRooms()
  ├── resetUnreadCount()      — 입장 시 0으로 리셋
  ├── incrementUnreadCount()  — SSE fallback 시 +1
  └── appendMessage()         — STOMP 수신 시 실시간 추가

신규 파일: src/store/chatStore.ts, src/types/chat.ts


2. 채팅방 목록 페이지 — ChatPage

기존 placeholder 화면에서 실제 채팅방 목록 렌더링으로 교체했습니다. GET /api/chat/rooms로 목록을 불러와 최근 메시지 시각 기준으로 정렬 표시합니다. 로딩/에러/빈 상태를 각각 분기 처리

수정 파일: src/pages/ChatPage.tsx, src/components/chat/ChatRoomItem.tsx (신규)


3. 채팅방 화면 — ChatRoomPage (신규)

파일: src/pages/ChatRoomPage.tsx

STOMP WebSocket으로 실시간 메시지를 송수신 함. 그룹 채팅(GROUP)과 1:1 채팅(DIRECT)을 chatRoomType으로 분기해 제목 및 정보 패널을 다르게 표시

기능 구현 방식
실시간 메시지 수신 @stomp/stompjs + SockJS, /topic/chat-room/{id} 구독
메시지 전송 /app/chat-room/{id}/send STOMP publish
이전 메시지 로드 스크롤 최상단 감지 → 커서 페이지네이션
입장 시 읽음 처리 POST /api/chat/rooms/{id}/read + unreadCount 0 리셋
채팅방 나가기 DELETE /api/chat/rooms/{id}/leave + 2단 확인 UI
정보 패널 (햄버거) 슬라이드 사이드 패널 — DIRECT: 상대방 닉네임, GROUP: 멤버 목록

그룹 채팅 멤버 목록 자동 갱신

정보 패널을 열 때 GET /api/chat/rooms/{id}/members를 호출해 최신 멤버 목록을 표시합니다. STOMP로 SYSTEM 메시지(입장·퇴장·강퇴)를 수신하면 멤버 목록을 자동 재조회해 UI를 동기화 함.

STOMP 구독 콜백 내에서 showInfoPanel 상태에 접근할 때 stale closure 문제가 발생할 수 있어, showInfoPanelRef를 별도로 유지해 항상 최신값을 참조하게 구현함.

// stale closure 방지 패턴
const showInfoPanelRef = useRef(false)
useEffect(() => { showInfoPanelRef.current = showInfoPanel }, [showInfoPanel])

// STOMP 콜백 내부 (클로저 시점에 ref로 최신값 참조)
if (message.messageType === 'SYSTEM' && showInfoPanelRef.current) {
  void fetchMembers()
}

멤버 목록은 HOST가 항상 상단에 오도록 isHost 필드 기준으로 정렬하고, 방장에게는 왕관(Crown) 아이콘을, 자신에게는 "(나)" 표시를 추가


4. 메시지 말풍선 — MessageBubble 닉네임·아바타 추가

파일: src/components/chat/MessageBubble.tsx

백엔드 ChatMessagesenderNickname 필드가 추가됨에 따라, 상대방 말풍선에 발신자 닉네임과 이니셜 아바타를 표시

  • 상대방: 아바타(이니셜) + 닉네임 헤더 + 말풍선
  • 본인: 말풍선만 (우측 정렬)
  • 시스템 메시지: 중앙 회색 텍스트

5. 1:1 채팅 연결 — MyRoomPage 지원자 채팅 버튼

파일: src/pages/MyRoomPage.tsx

지원자 목록에서 "채팅" 버튼 클릭 시, 기존 하드코딩 경로 대신 POST /api/rooms/{roomNo}/direct-chat/{applicantUserNo}를 호출해 DIRECT 채팅방 번호를 받아 /chats/{chatRoomNo}로 이동. 로딩 중 버튼 비활성화 처리를 포함


6. SSE 알림과 채팅 뱃지 연동 — App.tsx

파일: src/App.tsx

SSE로 NEW_MESSAGE_RECEIVED 이벤트 수신 시, GET /api/chat/rooms를 다시 호출해 chatStore를 서버 최신 상태로 갱신. 이를 통해 하단 탭의 읽지 않은 채팅 뱃지가 SSE 수신 즉시 반영

SSE NEW_MESSAGE_RECEIVED
  └── getChatRooms() → setChatRooms()   (서버 최신 상태로 전체 갱신)
  └── fetch 실패 시 fallback:
        incrementUnreadCount(relatedId) + updateRoomOnNewMessage()

로그인 이벤트(onAuthChange)에서도 getChatRooms()를 호출해, 로그인 직후 뱃지가 즉시 표시되도록 함

현재 보고 있는 채팅방의 메시지 알림은 토스트를 표시하지 않음. (window.location.pathname 검사)


버그 수정

BUG-1: 룸메이트 추가/퇴출 후 인원 표기 오류 (5/4명)

  • 원인: displayMembers에 서버에서 받은 room.currentMateCount를 사용해, 클라이언트 상태(roommates 배열)가 변해도 표기가 갱신되지 않음
  • 수정: room.currentMateCountroommates.length — 로컬 상태와 동기화
  • 파일: src/pages/MyRoomPage.tsx:1051

BUG-2: SSE 재연결 시 EventSource 강제 close로 자동 재연결 비활성화

  • 원인: eventSource.onerror에서 eventSource.close()를 직접 호출해, 브라우저 내장 자동 재연결(exponential backoff)이 취소됨
  • 수정: close() 호출 제거 — 브라우저가 재연결 타이밍을 관리하도록 위임
  • 파일: src/services/notification.ts

BUG-3: 방 지원 API 경로 불일치

  • 원인: 백엔드 엔드포인트 변경(/join-request/request)을 FE가 반영하지 않아 지원 API 404 응답
  • 수정: ApplyRoomModal.tsx, RoomSearchPage.tsx, MyRoomPage.tsx에서 경로 일괄 수정

체크리스트

  • 로그인 상태 변화 시 채팅 목록 즉시 갱신
  • STOMP 연결 끊김 시 reconnectDelay: 5000 자동 재연결
  • 채팅방 비멤버 진입 시 NOT_CHAT_ROOM_MEMBER 에러 처리 + 목록으로 이동
  • 방장 나가기 시 HOST_CANNOT_LEAVE 에러 메시지 안내
  • 모바일 vh 대응 (var(--vh, 100dvh))
  • 스크롤 관성 터치 최적화 (-webkit-overflow-scrolling: touch)

스크린샷

스크린샷 2026-03-23 19 36 51 스크린샷 2026-03-23 19 37 03 스크린샷 2026-03-23 19 37 20

@ydking0911 ydking0911 requested a review from KoungQ March 23, 2026 10:40
@ydking0911 ydking0911 self-assigned this Mar 23, 2026
@ydking0911 ydking0911 linked an issue Mar 23, 2026 that may be closed by this pull request
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
fe Ready Ready Preview, Comment Apr 2, 2026 3:03am

@ydking0911 ydking0911 changed the title feat: 실시간 채팅 UI 구현 및 품질 개선 [FEAT] 실시간 채팅 UI 구현 및 품질 개선 Apr 2, 2026
@ydking0911 ydking0911 merged commit 40fcf11 into main Apr 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 실시간 채팅 UI 구현

2 participants