-
실시간 채팅 구현개발공부/React 2024. 1. 24. 21:10
본 글은 React에서 Websocket & STOMP 를 사용해 실시간 채팅을 구현한 내용입니다.
(자세히 알고 싶다면 링크를 타고 들어가서 확인해보면 될 거 같다.)
두 가지 프로토콜이 어떤 특징을 가지고 있어서 실시간 채팅을 구현할 수 있는지 간단하게 정리해봤다.
Websocket
양방향 통신을 지원하며, 지속적인 연결을 통해 실시간 데이터 전송을 가능하게 해줌
STOMP
메시지 기반의 프로토콜로 쉬운 구현과 클라이언트-서버 간의 효과적인 양방향 통신을 제공실시간 채팅 구현
두 프로토콜의 특징을 알아봤으니 이제 실제로 활용해서 기능을 구현해보려고 한다.
먼저 단계를 설명하자면 아래와 같다.
- SockJS 객체를 생성합니다. (웹소켁 연결을 위한 객체 생성)
- STOMP 객체를 생성합니다. (STOMP 객체는 SockJS 객체를 기반으로 하여 웹소켓 통신을 위한 객체)
- STOMP 객체의 connect() 메서드를 사용하여 웹소켓 연결을 설정합니다.
- STOMP 객체의 subscribe() 메서드를 사용하여 채팅방을 구독합니다.
- STOMP 객체의 send() 메서드를 사용하여 채팅 메시지를 보냅니다.
위의 단계를 코드로 구현하면 아래와 같다.
import SockJS from "sockjs-client"; import { CompatClient, Stomp } from "@stomp/stompjs"; const ChatInputForm = () => { // ... 생략 // 1. SockJS 객체 생성 const socket = new SockJS("주소"); useEffect(() => { // 2. Stomp 객체 생성 const stompClient = Stomp.over(socket); // 3. Stomp 객체 사용해 연결 설정 stompClient.connect( { Authorization: accessToken, // 토큰 넣어주기 }, () => { client.current = stompClient; // 4. Stomp 객체의 subscribe 사용해 채팅방 구독 client.current.subscribe( `/sub/chat/room/${selectChat}`, (message) => { if (message && message.body) { var recv = JSON.parse(message.body); setMsgList(recv); } }, { Authorization: accessToken, simpDestination: selectChat, } ); } ); return () => { if (client.current) client.current.disconnect(); // 컴포넌트가 언마운트되면 연결 종료 }; }, [selectChat]); // ... 생략 const feedAddMutation = useMutation(addPhotoChatRoom, { onSuccess: (response) => { const url = response.data.data; // 5. Stomp 객체의 send 사용해 채팅 메시지 전달 client.current!.send("/pub/chat/message", {Authorization: accessToken}, JSON.stringify({type:"IMAGE" ,roomId: selectChat, message: inputValue, imageUrl: url})); }, }); // ... 생략 };
문제 발생?!
사실 위의 방법이 실시간 채팅 구현할 때 흔히 사용되는 방법이라서 연결하는데 큰 어려움은 없었다.
제일 고민이 많았던 부분은 오히려.. 채팅방 변경 시 바로 반영되지 않는 문제였다.
첫 번째로 선택한 채팅을 제대로 동작하는데, 두 번째로 들어간 채팅은 정상적으로 작동하지 않았다.
(내가 만들었던 프로젝트는 사용자가 여러 채팅방에 들어갈 수 있다.)
이유를 찾아보니 이전 코드는 첫 렌더링될 때만 동작해서 채팅방이 변경되었을 때 STOMP 클라이언트 생성 및 연결 로직이 실행되지 않아서였다. (+ 연결 종료 로직도 없었음!)
그래서 useEffect를 사용해 채팅방이 선택될 때마다 이전 연결은 종료하고 새롭게 생성 및 연결되도록 했다!
사실 제일 기본인 내용인데 처음 해보는거라서 놓쳤었던 거 같다! ㅎㅎ
다른 사람들은 내 글을 읽고 나와 같은 실수를 안했으면 좋겠다 :)
728x90'개발공부 > React' 카테고리의 다른 글
[React] fetch와 axios (0) 2024.03.25 [React] useState, useReducer hook (0) 2024.03.02 상태 관리 (0) 2024.01.16 DOM에 직접 접근하기 (useRef) (0) 2023.10.26 리액트 프로젝트 구조 (0) 2023.10.25