SocketIO를 이용한 채팅 구현하기

해준박·2023년 11월 2일
0

소켓을 배웠으니 이번 프로젝트에 적용해보자

그 전에 namespace 와 room 에 대해 알고가야한다
[SOCKET] 📚 Namespace & Room 기능 이해하기

위 블로그를 보고 이해한거는

Namespace = 채널
Room = 방

느낌이다

현재 진행중인 프로젝트에는 방하나에 2명만들어가서 1대1 채팅이기에 서로가 있는 roomId방에만 채팅을 보내면 된다

Client

// 소켓스테이트 생성
const [socket, setSocket] = useState<Socket | null>(null);

원래는 socekt 변수를 생성하고 거기에 바로 서버에 소켓을 연결했는데,

채팅을 치거나, 칠때마다 화면에 렌더링 되면서 socket을 계~~~속해서 재연결을 시켜줬다
무한 응답요청이 일어난거임.

그래서 스테이트 값을 만들어서 연결이 되었을 경우에는 다시 재연결하지 않도록했다.

// ... 중간 코드 생략

 useEffect(() => {
    const connectSocket = () => {
      const socketServer = io("https://ikw-market.shop/chat");

      socketServer.on("connect_error", (error) => {
        console.error("Socket connection failed:", error);
        setConnected(false);
      });

      socketServer.emit("enter_room", { roomId });
      setConnected(true);
      setSocket(socketServer);

      // 컴포넌트 언마운트시 실행되는 함수
      return () => {
        if (socketServer) {
          socketServer.disconnect();
          setConnected(false);
        }
      };
    };

    if (!isLogin) {
      navigate("/login");
    } else {
      return connectSocket();
    }
  }, [navigate, isLogin]);

소켓과 연결이 된다면 roomId에 접속 할 수 있게 된다
그리고 언마운트, 페이지를 나가거나 새로고침을 할 경우 소켓을 연결 해제한다

Server

// io.of() 채널 만들어주는 메서드, "/chat 채널"
const chat = io.of("/chat").on("connection", (socket) => {
  console.log("Socket connected!");
  //console.log("socket rooms : ", socket.rooms);
  socket.on("enter_room", ({ roomId }) => {
    // "socket join 메서드를 사용하면 인자로 전달한 방으로 연결."
    socket.join(roomId);
  });
  // 클라이언트에서 연결 해제 이벤트를 처리
  socket.on("disconnect", () => {
    console.log("Socket disconnected!");
  });

  socket.on("message", (message, { roomId }) => {
    //해당 채팅방으로 메시지를 보낸다.
    chat.to(roomId).emit("message", message);
    // io.emit("message", { name, message });
  });
});

서버는 간단하다. 클라이언트로부터 이벤트를 받았을때, 해당 이벤트의 콜백함수를 호출하고

호출문에는 해당방에 이벤트명과 매개변수(메시지데이터)를 클라이언트로 보내는 emit을 실행시킨다

클라이언트에서 메시지를 받고 저장하기

메시지를 주고 받은 내역들을 볼 수 있도록 데이터베이스에 저장하고 불러올수있게 해줘야 한다

메시지를 보냈을때 소켓에 전달하고 데이터베이스에 저장하는 함수를 호출한다

roomId = 채팅방의ID 이기에 해당 채팅방에 메시지데이터들을 저장하고 데이터베이스에 저장

불러올때도 roomId을 이용해 받아 올 수 있다.

// 메시지를 보냈을 때 발생하는 함수
const writeMessageLogAPI = async (message: IChatMessage) => {
    const { state } = await (
      await axios.post(`https://ikw-market.shop/api/chats/chat/${roomId}`, { message }, { withCredentials: true })
    ).data;
};

// 메시지 불러오기
const readChatRoomMessageAPI = async () => {
  const { state, chatRoom } = await (
    await axios.get(`https://ikw-market.shop/api/chats/${roomId}`, { withCredentials: true })
  ).data;

  setChat([...chatRoom.message_log]);
};

profile
기록하기

0개의 댓글