사용자가 입장할 때마다 모든 채팅을 다시 처음부터 불러오면 사용자 입장에서 불편함을 느낄 수 있다.

따라서 채팅을 전역상태로 관리하기로 결정했다.

우선 채팅데이터를 저장할 chatLogAtom이라는 atom을 하나 생성하자. 구조는 아래와 같다.

즉, key는 각 방의 고유 id며 value는 채팅 데이터다.

고려할 점

따라서 key는 logId로해서 중복 제거를 자동을 해주고, 순서 보장을 해주는 Map 자료구조를 사용하기로 했다.

export const chatLogAtom = atom<Record<string, Map<string, ChatLog>>>({
  key: 'chatLogAtom',
  default: {},
});

export interface ChatLog {
  message: string;
  userId: string;
  type: 'message' | 'in' | 'out' | 'kick';
  time: Date;
}

즉, chatLogAtom에 저장되는 예시는 아래와 같다.

{
	190305 : new Map([
    [
        "65728511bb2a8dabf82b6768",
        {
            "message": "fdfs님이 입장하셨습니다.",
            "type": "in",
            "time": "2023-12-08T02:53:05.585Z"
        }
    ],
    [
        "65728516bb2a8dabf82b6796",
        {
            "message": "재밌나요",
            "userId": "65728511bb2a8dabf82b676a",
            "type": "message",
            "time": "2023-12-08T02:53:10.950Z"
        }
    ],
		])
		,

	10205: new Map([
    [
        "65728511bb2a8dabf82b6768",
        {
            "message": "fdfs님이 입장하셨습니다.",
            "type": "in",
            "time": "2023-12-08T02:53:05.585Z"
        }
    ],
    [
        "65728516bb2a8dabf82b6796",
        {
            "message": "재밌나요",
            "userId": "65728511bb2a8dabf82b676a",
            "type": "message",
            "time": "2023-12-08T02:53:10.950Z"
        }
    ],
		])

}

type은 4개의 경우가 있다. 아래와 같은 4가지의 타입으로 나눈 이유는 message와 다르게 나머지 3개의 이벤트가 발생했을 때는 다른 UI를 보여주도록 하기 위해서다.

message 사용자가 입력한 채팅
in 사용자 입장
out 사용자 퇴장
kick 사용자 강퇴

예시는 다음과 같다.

vv.PNG