React.js

Ref와 Polling 방식을 사용하여 게임 데이터 준비 이후 실행 처리

Chunho 2024. 10. 8. 20:05

서버에서 응답으로 내려주는 데이터 중 게임 실행 준비가 완료되었다는 상태가 있을 경우, 폴링을 사용하여 로딩 Indicator를 돌리다가 실행 처리를 해줄 수 있다.

 

위 기능을 간단하게 구현해보기 위해 hook을 하나 만들어주었다.

 

const wrapPollingRef = useRef(false);

 

우선 Ref 하나를 생성해 준다.

  const { mutate: play, isLoading } = usePostAPIExEndPoint({
    mutation: {
      onSuccess: (data) => {
        if (data.result === "SUCCESS") {
          showLoading();
          setGameStatus({
            ...gameStatus,
            playId: data.playId,
          });
          wrapPollingRef.current = true;
        } else {
          openErrorModal();
        }
      },
      onError: () => {},
    },
  });

 

이후 Play버튼 클릭 시의 이벤트를 제어해주는 mutation을 만든 뒤 play함수는 hook을 연결하는 컴포넌트에서 받아 이벤트에 연결한다.

 

  const { data: resultData } = useGetExample(gameStatus.id, {
    query: {
      enabled: wrapPollingRef.current && gameStatus.id !== -1,
      refetchInterval: 1000,
      onSuccess: (data) => {
        if (data.completed && wrapPollingRef.current) {
          hideLoading();
          setGameStatus({
            ...gameStatus,
            playStatus: "IN_PROGRESS",
          });
          wrapPollingRef.current = false;

          (async () => {
            setPageTransition(true);
            await WaitForSeconds(500);
            setPageTransition(false);
            playAction();
          })();
        }
      },
    },
  });

 

이후 게임 실행이 준비될 때 까지 계속해서 요청을 하며, 준비가 된 경우 로딩 인디케이터를 숨기고 게임을 진행하는 간단한 기능을 만들 수 있었다.

 

추가적으로 버튼을 연속해서 빠르게 클릭하는 경우 서버로 여러개의 요청이 들어가는 것을 방지하는 예외처리를 하기 위해 

 

export const throttling = (throttleTimePerMs = 500) => {
  let timer: ReturnType<typeof setTimeout> | null = null;

  const throttleFunc = (callbackFunc: () => void) => {
    if (!timer) {
      timer = setTimeout(() => {
        timer = null;
      }, throttleTimePerMs);

      try {
        callbackFunc();
      } catch (error) {
        console.error("Error in throttled function:", error);
        if (timer) {
          clearTimeout(timer);
          timer = null;
        }
      }
    }
  };

  return throttleFunc;
};

 

위와 같이 간단한 쓰로틀링 기능을 추가로 만들어줬다.

 

 

연속 이벤트 자체를 방지하는것이 아닌, 순간적으로 많은 요청이 들어가는것만 방지하기 위해서라면 useMutation이 제공하는 isLoading을 사용하는 것도 좋을 것 같다.