채팅 작성 : 키보드 이벤트 시. socket을 통해 채팅 방 내 모든 socket에 타입중이라는 메시지를 전송함.

채팅 전송 : socket이 연결되어 있다면, typing을 멈추고, http 통신으로 message를 서버에 등록시키는 비동기 이벤트를 생성한다.
그와 동시에 socket 서버를 통해, 데이터를 브로드캐스팅한다.

postMessage
import api from "@/_lib/fetcher";
export default async function postMessage(body: any, token: string) {
const data = await api.post({ endpoint: `api/message`, body, authorization: token, apiType: true });
return data;
}
채팅 브로드캐스팅 : summit 시 입력된 메시지를 저장한 뒤, 메시지가 도착했다는 이벤트와 함께 메시지를 보냄.

클라이언트에서 신규 데이터 처리 : 받은 메시지를 마지막 메시지 배열로 추가한다.
useEffect(() => {
if (socket) {
socket.on("message received", (newMessageReceived: IMessage) => {
// Check for duplicate messages
setMessages((prevMessages) => {
const messageExists = prevMessages.some((message) => message._id === newMessageReceived._id);
if (!messageExists) {
return [...prevMessages, newMessageReceived];
}
return prevMessages;
});
});
}
return () => {
if (socket) {
socket.off("message received");
}
};
}, [socket]);
import { IChat } from "./IChat";
import { IUser } from "./IUser";
export interface IMessage {
chat: IChat;
content: string;
readBy: IUser[];
sender: IUser;
createdAt: Date;
updatedAt: Date;
__v: number;
_id: string;
}
백엔드에서 Chat을 Join 시킨 뒤, 프론트에 전달하고, 다시 돌려받는 과정을 거친다.
이는 그리 좋은 방식은 아닌듯하다.
물론 소켓 통신 도중에, DB와 통신하여, chat과 관련된 데이터를 불러오는 것 또한 시간이 걸리는 동작이겠지만, 아마 다른 방식이 있지 않을까 생각한다. 기존의 room을 사용한다면…
// 브로드케스트 : 자신 이외의 모든 클라이언트에게 브로드캐스트
socket.broadcast.to(chat.id).emit("message received", newMessageReceived);
// 모든 클라이언트에 송신
socket.in(chat.id).emit("message received", newMessageReceived);
https://github.com/SWYP-LUCKY-SEVEN/chat-server/pull/5
현재 채팅방에 입장할 경우. 이전의 모든 채팅 데이터를 한번에 불러오게된다.
채팅 기록이 쌓일수록 해당 방식은, HTTP 통신으로는 감당할 수 없을만큼 데이터가 커질 뿐 아니라, 백엔드에서 데이터를 처리하는 과정에 있어서 또한 결코 효율적이지 않다.
사용자는 쌓여온 모든 채팅 데이터가 한순간에 필요한 순간은 거의 없기 때문이다.