사용자가 입장할 때마다 모든 채팅을 다시 처음부터 불러오면 사용자 입장에서 불편함을 느낄 수 있다.
따라서 채팅을 전역상태로 관리하기로 결정했다.
우선 채팅데이터를 저장할 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 | 사용자 강퇴 |
예시는 다음과 같다.