stomp(socket)으로 만든 채팅 목록에 들어오는 채팅 알림 업데이트 하기

채팅 목록 업데이트 기능 만들기

이전에 소켓의 연결을 통해, 새로운 채팅이 소켓에 들어오는 상황이 발생하면 그 메세지를 저장하는 기능을 만들었습니다. 이후 메세지 목록 내에서도 업데이트가 되는 상황이 발생하면, 이 사항을 바로 반영하는 기능을 넣어야 했습니다.

해당 기능을 만들기 위해서 거쳐야 하는 단계는 다음과 같았습니다.

  1. 새로운 채팅이 들어오면 채팅의 정보를 바로 가져오기(id, contents)
  2. 새로운 채팅의 정보와 일치하는 채팅 찾기
  3. 해당 채팅 업데이트 하기
  4. 업데이트 된 정보 처리하기

새로운 채팅의 정보 가져오기

export type ChatroomsUpdate = {
  id?: number;
  contents?: string;
};

export const chatroomsUpdateState = atom<ChatroomsUpdate>({
  key: "chatroomsUpdate",
  default: {},
});

// ChatroomsItem.tsx
const { id: updateId, contents: updateContents } =
  useRecoilValue(chatroomsUpdateState);

현재 사용 중인 Recoil의 특성상, 특정 상태의 업데이트가 이루어지게 되면 해당 상태를 쓰는 곳에서도 업데이트가 이루어지기 때문에 해당 값을 가져오는 것만으로 업데이트가 가능했습니다.

일치하는 채팅 찾기 및 업데이트

// ChatroomsItem.tsx
const [curUnreadCount, setCurUnreadCount] = useState(unreadCount);
const [curRecentMessage, setCurRecentMessage] = useState<string | undefined>(
  recentMessage
);

useEffect(() => {
  if (chatRoomMemberId !== updateId) return;

  setCurRecentMessage(updateContents);
  setCurUnreadCount((prev) => prev + 1);
}, [updateContents]);

이후 useEffect를 통해 updateContents가 변하는 경우마다 특정 상황이 이루어지도록 했습니다. 여기서 id값이 일치하는 경우에만 다음 작업이 이루어질 수 있도록 했으며, 이를 통해 해당 id를 찾는 작업을 진행했습니다.

id가 일치하는 경우, 해당 항목의 메세지를 새롭게 설정된 메세지(setCurRecentMessage)로 바꾸고, 읽지 않은 개수(setCurUnreadCount)도 증가하도록 설정했습니다.

업데이트된 정보 처리하기

하지만, 이렇게 설정할 경우, 한 가지 문제가 발생하게 됐는데, updateContents라는 정보가 다른 페이지에 있다가 넘어오는 경우 useEffect의 특성으로 인해 렌더링 후 바로 해당 id의 정보가 업데이트되어 버린다는 것입니다. 즉, 읽지 않은 항목이 1개씩 늘어나게 됩니다.

이 부분을 해결하기 위해서 두 가지 중 하나를 골라야했습니다.

  1. 업데이트가 이루어질 때마다 updateContents를 초기화하기
  2. updateContents를 특정 타이밍에 초기화하기

첫 번째 경우의 수를 사용할 경우, 초기화를 하는 중간에 새로운 정보가 socket을 통해 들어오게 되면 제대로 된 데이터 처리가 되지 않을 가능성이 존재합니다. 이로 인해 updateContents를 일정 시점에 초기화해주어야 하는데, 그 시점을 ‘채팅 목록 페이지를 나가는 시점’으로 했습니다. 이를 구현하기 위해 현재 페이지 내의 useEffect에 리턴 함수를 적용해주었습니다.

// Chatrooms.tsx
useEffect(() => {
  return () => setChatroomsUpdate({});
}, []);

🔎 여기서 현재 의문점이 드는 것은, 업데이트가 발생할 때마다 모든 채팅 한 번씩 검사는 거친다는 점에서, 렌더링에는 큰 무리가 없지만 계산이 계속 적용된다는 것에 문제가 있지는 않을까하는 생각이 들었고, 추후에 이것 외에 다른 방식으로 id값을 비교할 방법이 있는지 알아보고자 합니다.