SSE를 이용한 실시간 채팅 성능최적화 버그 해결

RuLu·2024년 4월 3일
2

React

목록 보기
12/15
post-thumbnail

끝난줄 알았는데 끝나지 않았던 SSE의 저주.. 사실 고치고 나서 새로운 버그를 발견했다고 하면 믿으시겠나요? ㅎ 그냥그냥 sse쓰지마십셔

섬네일

요토가 떠먹여준 버그 픽스 + 블로그 입니다. 아주 이슈와 PR에 야무지게 작성해줘서 이렇게 날먹해도 되나 싶습니다ㅎ.. 암튼 요수리마수리토깽에게 치얼스✨ 

틀린그림 찾기 ON

<고치기 전>

<고친 후>

고치기 전 고친 후

고치기 전에는 빈번하게 채팅이 늦게 올라오는 경우가 발생했다. 정확히는, 메시지를 수신받은 후 사용자가 스레드 리스트 컴포넌트의 state를 변경시키는 행동(채팅창에 무언가를 입력, 공지 여부 체크박스 선택/해제)을 할 때에서야 비로소 반영되지 않았던 최신 메시지가 반영되는 문제이다.

문제 발생 원인

SSE에서 채팅창을 갱신하기 위해 사용하는 setQueryData 의 경우, 함수 형태로 사용할 때 기존 데이터(oldData)와 새롭게 갱신할 데이터(newData)의 참조가 서로 달라야 한다. 더 어렵게 이야기하면 immutable하게 변수를 관리해야만 한다. 그렇지 않을 경우, tanstack-query에서 새로운 값으로 갱신되었음을 감지하지 못해 업데이트가 일어나지 않을 수 있다고 한다.

기존 방식의 경우, old에 직접 변경사항을 내고 old를 반환했기 때문에 참조가 변하지 않는다.

<고치기 전>

queryClient.setQueryData<InfiniteData<ThreadsResponse>>(
  ['threadData', teamPlaceId],
  (old) => {
    if (old) {
      old.pages[0].threads = [newThread, ...old.pages[0].threads];
      return old;
    }
  },
);

<고친 후>

oldData 에서 아예 새로운 변수인 newData 를 만들어 이를 반환해 참조가 변하도록 변경한다.

queryClient.setQueryData<InfiniteData<ThreadsResponse>>(
  ['threadData', teamPlaceId],
  (oldData) => {
    if (oldData) {
      const newFirstPageThreads: ThreadsResponse = {
        threads: [newThread, ...oldData.pages[0].threads],
      };
      const newData = {
        pageParams: oldData.pageParams,
        pages:
          oldData.pages.length === 1
            ? [newFirstPageThreads]
            : [newFirstPageThreads, ...oldData.pages.slice(1)],
      };

      return newData;
    }
  },
);

이러면 버벅거리는 문제는 해결된다 ^-^

또 다른 버그,,,,

새로운 버그는 재연결시 채팅데이터 조회요청을 보내는 이 부분에서 발생하는 것으로 유추되는데, 재연결과 채팅 송신이 겹쳐지면 보낸쪽에서 채팅을 볼 수 없는 문제…

eventSource.addEventListener('connect', () => {
      queryClient.invalidateQueries([['threadData', teamPlaceId]]);
  });

다시 틀린그림찾기 ON

문제점 등장 이게 정상
오른쪽 사진에서 `그냥 못쓰는 거여~` 이거 보낼 때 딱 SSE 재연결 타이밍이었는데 나한테 왼쪽처럼 보여서 새로고침하니까 이미 보내져 있었다. 아마 받는쪽에서는 문제 안되는 듯? 나중에 고치면 추가할게요,,ㅋ
profile
프론트엔드 개발자 루루

0개의 댓글