본문 바로가기
React

React websocket을 이용한 1:1 채팅 만들기

by 왜안돼요 2024. 7. 10.
728x90

엉엉 울면서 구현한 채팅 

레지고.

 

WebSocket이란??

웹소켓은 웹 앱과 서버 간의 지속적인 연결을 제공하는 프로토콜이다. 이를 통해 서버와 클라이언트간에 양방향 통신이 가능해진다.

HTTP와는 달리, 웹소켓 연결은 한 번 열린 후 계속 유지되므로, 서버나 클라이언트에서 언제든지 데이터를 전송할 수 있다.

 

이때 데이터는 패킷(packet) 형태로 전달되며, 전송은 커넥션 중간과 추가 HTTP 요청 없이 양방향으로 이뤄진다!

이런 특징 때문에 웹소켓은 온라인 게임이나 주식트레이딩 시스템 같이 데이터 교환이 지속적으로 이뤄져야 하는 서비스에 적합하다

 

사용하기

webSocket 연결 

const [messages, setMessages] = useState<string[]>([]);
const webSocket = useRef<WebSocket | null>(null);

useEffect(() => {
  webSocket.current = new WebSocket('ws://websocket-url');
  webSocket.current.onopen = () => {
    console.log('WebSocket 연결!');    
  };
  webSocket.current.onclose = (error) => {
    console.log(error);
  }
  webSocket.current.onerror = (error) => {
    console.log(error);
  }
  webSocket.current.onmessage = (event: MessageEvent) => {   
    setMessages((prev) => [...prev, event.data]);
  };

  return () => {
    webSocket.current?.close();
  };
}, []);

 

* ws 프로토콜 말고 wss://라는 프로토콜도 있는데 HTTP와 HTTPS의 관계와 유사하다.

웹소켓

더 자세한것은 문서를 읽어보자!

 

메세지 전송

//메시지 전송 함수
  const sendMessage = (text: string, image: string, sender: string) => {
    if (!text.trim() && !image) {
      // 텍스트와 이미지가 모두 없는 경우 메시지를 보내지 않음
      return;
    }
    webSocketRef.current?.sendMessage({ text, image, sender });
    // console.log("메세지 전송:", text, "사진:", image, "보내는 사람", sender)
  }

 

메세지 표시

<div>
    {messages?.map((message, index) => (
      <div key={index}>{message}</div>
    ))}
  </div>

컴포넌트 내에서 메세지 상태를 사용하여 수신된 메세지를 표시한다.

 

여기까지가 서치했을때 나오는 흔한 예시들이다...

 

 

나는 다른곳에서도 빼 쓸 수 있게 클래스로 만들라는 조언을 얻었다

정말.. 예시도 없고.. 엉엉 울면서 했다

 

utils/chatSocket.ts

import useMessageStore from '@/stores/useMessageStore';

const { VITE_WEB_SOCKET } = import.meta.env;

class ChatSocket {
  webSocket: WebSocket | null = null;
  constructor(chatRoomId: number | null) {
    this.webSocket = new WebSocket(`${VITE_WEB_SOCKET}/chat/${chatRoomId}/`);

    // 웹소켓 연결
    this.webSocket.onopen = function () {
      console.log('웹소켓 연결 ^_^');
    };
    // 웹소켓 종료
    this.webSocket.onclose = error => {
      console.log('종료~', error);
    };
    // 웹 소켓 에러
    this.webSocket.onerror = function (error) {
      console.log('웹 소켓 에러', error);
    };

    // 웹소켓으로부터 메시지를 받았을 때 실행되는 함수
    this.webSocket.onmessage = event => {
      const data = JSON.parse(event.data);
      // setMessage((prev) => [...prev, data]);
      useMessageStore.getState().addMessage(data);
      // console.log("온메세지에서 실시간 메세지 받았읍니다.", data)
    };
  }
  close() {
    this.webSocket?.close();
  }

  sendMessage(message) {
    this.webSocket?.send(JSON.stringify(message));
  }
}
export default ChatSocket;

이렇게만들어주고 필요한곳에서 임포트해서 쓰면 된다!

import ChatSocket from '@/utils/chatSocket';

const Chat = () => {
  let webSocketRef = useRef<ChatSocket | null>(null);
  const { chatRoomId } = useChatRoomStore()

  //페이지 이동시 웹소켓 종료
  useEffect(() => {
    return () => {
      webSocketRef.current?.close()
    }
  }, [])



  useEffect(() => {
    if (chatRoomId) {
      webSocketRef.current = new ChatSocket(chatRoomId);

      window.addEventListener('beforeunload', () => {
        webSocketRef.current?.close()
      })

      return () => {
        webSocketRef.current?.close()
      }
    }
  }, [chatRoomId])

  //메시지 전송 함수
  const sendMessage = (text: string, image: string, sender: string) => {
    if (!text.trim() && !image) {
      // 텍스트와 이미지가 모두 없는 경우 메시지를 보내지 않음
      return;
    }
    // if (webSocketRef.current) {
    //   webSocketRef.current.sendMessage(JSON.stringify({
    //     message,
    //     image,
    //   }));
    //   console.log("메세지 전송함수", message, "사진", image);
    // }



    webSocketRef.current?.sendMessage({ text, image, sender });
    // console.log("메세지 전송:", text, "사진:", image, "보내는 사람", sender)
  }

 

참고

React에서 WebSocket을 사용하는 방법

최근댓글

최근글

skin by © 2024 ttuttak