React에서 중복호출방지

Suyo·2025년 2월 17일
0

개요

프로젝트 진행중에 중복클릭이 가능하여 같은 폼을 여러번 보내는 문제가 발생했다. 개발자도구에서 network throttling을 3g로 걸어주니 서버에 호출을 받기까지 시간이 2초정도 걸리더라...
이렇게 개발자가 의도하지 않은 동작을 막기위해 isLoading 메서드를 사용했다.

isLoading의 문제

const [isLoading, setIsLoading] = useState(false);

const handleConfirmSubmit = async () => {
    if (isLoading) {
      return;
    }

    setIsLoading(true);
    try {
      const sushiData = {
        title,
        content,
        maxAnswers,
        category,
        sushiType,
      };
      console.log("등록된 내용:", sushiData);
      const response = await dispatch(createSushi(sushiData));
      const { success, data, error } = response.payload;
      const { token } = data;
      const shareUrl = `share/${token}`;
      setShareUrl(shareUrl);
      console.log("공유 URL:", shareUrl);
      setShowModal(false);
      setShowCompleteModal(true);
    } finally {
      setIsLoading(false);
    }
  };

이런식으로 isLoading 메서드를 useState를 통해 걸어줄 수 있다. 이런 방식은 다음과 같은 문제점을 가지고 있다.

  1. 경쟁 상태(Race Condition): 여러 요청이 동시에 발생할 경우, isLoading 상태가 정확하게 반영되지 않을 수 있다.
  2. 상태 업데이트 지연: React의 상태 업데이트는 비동기적이므로, isLoading 상태가 변경되기 전에 여러 번의 클릭이 발생할 수 있다.
  3. 컴포넌트 언마운트 문제: 요청 중에 컴포넌트가 언마운트되면 isLoading 상태가 적절히 초기화되지 않을 수 있습니다.

이러한 문제들을 방지하기 위해 useRef를 사용하는 것이 권장된다.

useRef를 사용하는 코드

const dispatch = useDispatch();
const isSubmittingRef = useRef(false);
const reRender = useCallback(() => {}, []);

const handleConfirmSubmit = async () => {
  if (isSubmittingRef.current) {
    return;
  }

  isSubmittingRef.current = true;
  reRender();

  try {
    const sushiData = {
      title,
      content,
      maxAnswers,
      category,
      sushiType,
    };
    const response = await dispatch(createSushi(sushiData));
    const { success, data, error } = response.payload;
    const { token } = data;
    const shareUrl = `share/${token}`;
    setShareUrl(shareUrl);
    setShowModal(false);
    setShowCompleteModal(true);
  } finally {
    isSubmittingRef.current = false;
    reRender();
  }
};

useRef를 사용하는 방식의 장점

  1. 즉각적인 값 업데이트: ref는 동기적으로 업데이트되어 경쟁 상태를 방지한다.
  2. 리렌더링 독립성: ref 값의 변경은 리렌더링을 트리거하지 않아 성능상 이점이 있다.
  3. 컴포넌트 생명주기 독립성: 컴포넌트가 언마운트되어도 ref 값이 유지된다.

결론

Claude와의 대화를 통해 useState를 통해 중복클릭 방지를 하는 방안을 적용했다. 그러다가 혹시 다른 문제가 발생하지 않을까? 하고 구글링을 시작했다. 그러다가 https://happysisyphe.tistory.com/72
사이트를 발견하고 useRef를 사용하는 방법을 적용했다. 또한 더욱 안정적인 방법 두가지 또한 알게 되었다.
AI에게만 의존하지말고 구글링도 계속해서 더 실력있는 개발자가 되자!

profile
Mee-

0개의 댓글