디바운스, 스로틀이 제대로 동작하지 않는 이유
Debounce 와 Throttle이란?
검색을 해보면 이미 사용 예시와 설명이 자세히 나와있다.
이벤트를 제어(제한)하는 방법으로,과도한 이벤트 횟수의 실행으로 이벤트 핸들러가 무거운 계산 및 기타 DOM 조작과 같은 작업을 수없이 많이 수행하는 경우 성능 문제가 발생하고 이는 사용자 경험자 경험을 망가뜨릴 것이다.이를 해결하기위해 콜백의 실행횟수를 제한하기위해 사용함.
디바운스
이벤트를 그룹화하여 특정시간이 지난 후 하나의 이벤트만 발생하도록 하는 기술
즉, 순차적 호출을 하나의 그룹으로 "그룹화"할 수 있다. 포인트는 맨 마지막 이벤트가 일어나고 일정시간 후에 딱 한번 실행된다!
스로틀
Throttle 은 이벤트를 일정한 주기마다 발생하도록 하는 기술
예를 들어 Throttle 의 설정시간으로 1초 를 주게되면 해당 콜백은 1초 동안 최대 한번만 실행됨. 1초 전에 쌓인 이벤트큐들은 모두 무시된다고 한다.
상황에 따라 어느 것이 유용할지 구분해야하지만 이미 잘 정리해놓은 블로그들이 많으니 그때마다 참조하는것도 좋을 것 같다 ㅎ
이번 포스팅에서는 실제 구현에 초점을 맞춰서 작성해보자!
디바운스 구현
보통 리액트에서는 lodash 패키지를 설치하여 사용한다.
import React from 'react'
import {firestore} from '../shared/firebase';
import {throttle,debounce} from 'lodash';
function Test() {
const [text,setText] = React.useState('');
const _debounce = React.useCallback(debounce(()=>{
console.log('debounce콜백호출');
},2000),[text]);
const changehandler = (e) => {
_debounce();
setText(e.target.value)
}
React.useEffect(() => {
return () => {
// debounce를 해제 해주어야합니다.
},[]),
return (
<div>
<input value = {text} onChange={changehandler}></input>
</div>
)
}
export default Test
사용할 때는 반드시 useCallback으로 디바운스 함수의 재생성을 막아야한다.
위 예시는 제대로 동작하지 않는다(useCallback의 의존성 때문에).
테스트로, 글자를 계속 쳐보자, 첫 타이핑을 하고, 2초뒤에 밀린 콜백이 실행되어 연속적으로 디바운스함수가 실행된다.
why?
이유는 리렌더링에 있다. text를 칠때마다 state값이 바뀌면서, 컴포넌트 리렌더링을 유발하는데, 리렌더링 될때마다 _debounce함수가 재생성 되기 때문이다.(dependency가 text 이므로) 이벤트 큐를 살펴보면,
글자를 칠 때마다 inputChangeHandler가 호출되고, 요 함수에서 _debounce()가 호출된다. 그리고 _debounce()가 이벤트 큐에 쌓일 것이다.
해당 렌더링시점에 새롭게 생성된 디바운스함수가 큐에 쌓일것이고, 이를 같은 디바운스함수로 인지하지못하기 때문에, 이전 렌더링시점에 이벤트 큐에 담겨있던 _debounce()를 무시하지 못하고 이벤트루프에 의해서 콜스택으로 불려진다. 즉 친 글자 수 만큼 디바운스함수가 호출된다.
해결방법 (의존성의 중요성)
const _debounce = React.useCallback(debounce(()=>{
console.log('debounce콜백호출');
},2000),[]);
useCallback의 의존성을 비우자. [] 로 설정하면 맨 처음 생성된 디바운스함수만 이벤트 큐에 쌓일것이다.
의존성을 적절히 사용하면 debounce함수내에서 컴포넌트의 상태값을 사용할때, refresh된 closure로 상태값에 접근할 수 있다.
위 경우에서는 디바운스 함수내에서 input의 text값을 사용하고싶다면, 매개변수로 상태값을 전달해서 사용하면 된다.
CleanUp을 꼭 해주자
클린업 함수에서, _debounce.cancel()을 달아주자.
컴포넌트가 언마운트 될 때, 직전 렌더링에서 생성된 debounce함수가 이벤트큐에 대기중이라면 삭제해주어야 불필요한 호출을 막을 수 있다.
다음편에서는 스로틀을 이용해서 무한스크롤을 구현해보도록 하자
Author And Source
이 문제에 관하여(디바운스, 스로틀이 제대로 동작하지 않는 이유), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@sae1013/디바운스-스로틀이-제대로-동작하지-않는-이유저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)