디바운싱은 동일한 요청이 짧은 시간내에 반복하여 들어왔을때, 마지막 요청만 처리하는 기법이다.
느린 처리속도로 인하여 사용자가 많은 POST요청을 짧은시간동안 빠르게 보냈을 경우, 예를들어 방 생성을 1초간 세번 요청한다면, 디바운싱이 없는 요청은 3번 다 요청이 갈것이고...요청이 3개 다 성공해도 문제지만, 성공하지 않는 경우도 문제다!
아무튼, 이를 방지하기위하여 디바운싱을 도입해야했다.
이때 요청은 React Query의 useMutation으로 보내는 상황! 어떻게 디바운싱을 걸어줄까?
react-query는 promise를 반환하는 함수를 받아 처리해주는 상태관리 라이브러리다.
debounce는 보통 promise를 반환하는 함수를 인자로 받아 클로저에 함수를 담고, 리턴한다.
이걸 조합해서 사용할 수 있을까?
const { mutate } = useMutation({
mutateFn: debounce(apiFn, 300),
})
안된다. 왜냐하면 debounce
자체는 Promise를 반환하는 함수가 아닌 함수이기 때문이다.
사용하려면 아래처럼 해야한다.
const debouncedFn = useDebounce(apiFn, 300)
const { mutate } = useMutation({
mutateFn: debouncedFn
})
debounce가 필요한곳 마다 debounce를 호출해야해서 좀 불편하다...그리고 버그도 있었다.
const useCreateGameRoom = () => {
const debouncedFn = useDebounce(apiFn, 300)
return useMutation({
mutateFn: debouncedFn
})
}
useMutation
을 한번 래핑한 훅에서 사용할거라 이렇게 쓰려했는데, 자기 멋대로 mutate가 발생했다.
요약한 문제는 다음과 같다.
1번은 쉽게 해결할 수 있을 것 같다.
래핑하지않고, debounced된 함수를 받는 것.
하지만 단 한개의 mutation
이라도 래핑해서 사용하는 건 이점이 꽤 컸다. (공통 옵션, 쿼리or 뮤테이션 키 전달, 명시적으로 어떤걸 호출하는지 알수 있다)
2번은 쉽진 않아 보였다. debounced된 함수를 전달하는게 아니라 useDebounceMutation
같은 함수를 따로 만들어야 했기 때문이다.
하지만 2번을 해결한다면, 1번도 자연스레 해결 될 터.
그렇게 머리를 꽁꽁 싸매고 있던 찰나 React Query 공식 깃허브의 이슈 중 하나를 보게되었다.
다양한 의견이 있었다. useDebounce라는 훅을 사용하는 사람도 있었고 자체제작한 함수를 사용하는 사람들도 있었다.
나는 그중 맨 마지막 함수에 꽂혔다 ㅎㅎ
출처 : https://github.com/TanStack/query/issues/293#issuecomment-1942398332
마지막 댓글달아주신 분이 남겨준 코드다.
장황했지만 꼭꼭 씹어먹으니 코드를 이해할 수 있었다.
골자는 useMutation
을 한번 래핑한 함수다. 그래서 타입이 좀 많다.
특히 그냥 mutate
는 리턴하면 안되서 타입에서 Omit<>
을 이용하여 제외시켰다.
timer
또한 따른 debounce
들과 비슷하게 ref
를 사용해서 저장한다.
그리고 호출하면 timer
를 지운다.
나는 이 코드를 사용하되 파라미터로 넘겨주는 duration
과 ...options
를 옵셔널한 타입으로 지정하고싶었다.
여기서 ...options
는 useMutation
에 전달하는 옵션이었다.
duration
은 물음표'?'를 붙여 옵셔널하게 만들 수 있었다.
그러면 rest parameter는 어떻게 옵셔널하게 만들까? 그냥 물음표를 갖다 붙이면 될까?
안된다...😭
ts에서 직접적으로 막아뒀으니 트릭을 사용해서 옵셔널하게 하는 행위는 지양하자!
결국 option전체를 받아서 옵셔널하게 만들었다.
어쨌든 문제는 해결했으니 다행이구나!
어려워보이는 타입스크립트 코드라도 읽어보면 의외로 쉬웠다. 이전에 React Query의 타입이 궁금해서 찾아봤던게 도움이 많이 되었다. 지식은 연결될때 그 빛을 발휘한다.
또 트러블 슈팅이 발생하면 공식 깃허브나 문서를 잘 찾아보자! 생각보다 많은 사람들이 같은 문제를 겪는다.
아닌 경우면...잘 생각해보자😮