Programming/Java Script

Debounce 라이브러리 쓰지 않고 구현해보기

감귤밭호지차 2024. 3. 20. 17:44

면접에서 왜 Debounce 라이브러리로 썼냐고 그래서.. 엄.. Um.. 그것이 간편하니까.. 라고 대답한 댕청한 나 ㅋ

 

Debounce 란 ( with Throttle ) 

우선 Debounce에 대해서 간단하게 설명하고 넘어가자. 

Debounce는 Throttle과 함께 대표적인 웹 최적화 기법 중 하나이다. 주로 네트워크의 불필요한 연속 요청을 방지해 주는 아주 고마운 친구이다. 

 

Debounce

이벤트를 그룹화해서 특정 시간이 지난 후 하나의 Event만 발생하도록 하는 기술.

100ms로 설정을 해두면 첫 Event 발생 후 100ms 동안 추가적인 이벤트가 발생하지 않는다면 함수를 실행하고, 100ms안에 추가적인 이벤트가 발생한다면 다시 이 Event를 기준으로 100ms 동안 추가적인 이벤트 발생 여부에 따라 함수를 실행하거나 실행하지 않습니다. 

 

 

 

 

Throttle

이벤트를 일정한 주기마다 발생하도록 하는 기술.

100ms로 설정을 해두면 첫 Event 발생 후 100ms 마다 함수가 실행됩니다. 

 

 

 

 

 

예를 들어 북마크를 누르는데 연속해서 톼과톼톼톼톼톼ㅗ탁 하고 100번 누루는 유저의 경우, 

100번 모두 북마크 저장, 북마크 취소 네트워크 요청을 해야 하는 것은 너~무나도 비효율적이지 않은가!!! 

 

 

그..그만 네트워크 요청 멈춰,..!

 

 

혹은 검색 키워드 입력하다가 관련 검색어 검색할 때  " ㄱ -> 가 -> 감 -> 감ㅅ -> 감사 " 이렇게 입력되는 순간 순간 모두 네트워크를 요청하는 것 또한! 비효율적이다 이말이다. 

 

 

이러한 불필요한 상황들을 마지막 요청만 캐치해서 네트워크 요청을 보내거나 일정 시간마다 요청을 해서 횟수를 줄여갈 수 있도록 해주는 아주아주!! 훌륭한 기법들이다. 

 

 

 

아래 영상이 Debounce를 적용하기 전 끔찍한 화면 사이즈 변경에 따른 값들이 출력되는 모습이다 으으으으으..;;;;

 

 

 

하지만 Debounce와 함께라면? 얍!

 

 

 

 

 

 

고급 표현으로 정리하자면,, 
Debounc와 Throttle은  DOM 이벤트를 기반으로 실행하는 자스를 성능상의 이유로 이벤트(EVENT)를 제어하는 방법입니다. 
북마크를 연속으로 클릭을 하거나 스크롤과 관련된 이벤트가 실행될 경우, 동작마다 많은 양의 Event가 발생합니다. 
이는 Event 발생 마다 callback이 발생하고 이를 매번 수행하는 것은 큰 리소스를 소모하게 되는 것입니다. 

 

 

 

 

 

 

 

라이브러리와 함께하는 Debounce : )

 

> 사용 라이브러리 : lodash

 

Lodash

_.defaults({ 'a': 1 }, { 'a': 3, 'b': 2 });_.partition([1, 2, 3, 4], n => n % 2);DownloadLodash is released under the MIT license & supports modern environments. Review the build differences & pick one that’s right for you.InstallationIn

lodash.com

 

설치 방법

$ npm i -g npm
$ npm i --save lodash

 

 

import _ from "lodash";   // import _ from "lodash.debounce"; 로 소환해도 됨 -> _();

const usingLodash = _.debounce(() => {  //debounce로 감싸주기
	doItSomethingLater();  // 실행할 함수
}, 100 );  // 100ms동안 디바운스 시간

throttle도 사용방법은 똑같다. _.throttle 로 사용하거나 import할 때  from "lodash.throttle" 로 소환해서 똑같이 원하는 시간 설정해주면 된다. 

 

 

 

노가다 Debounce... : (

setTimeout를 사용해서 구현하는 방법. 결국은 특정 시간을 이용해서 실행해야 할 함수를 딜레이 하는 거라서.. 

 

 

React 컴포넌트 내부에서 useEffect를 사용한 코드

const [ query, setQuery ] = useState("");
const [ tempQuery, setTempQuery ] = useState(query);

useEffect(() => {
	const debounce = setTimeout(() => {
    	return setQuery(tempQuery);
    }, 100);
    
    return () => clearTimeout(debounce);
}, [tempQuery])

 

 

 

customHook으로 개저하여 사용한 코드 

function useDebounce ( defaultValue ){
	const [ query, setQuery ] = useState( defaultValue );
    const [ debounceQuery, setDebounceQuery ] = useState( defaultValue );
    
    useEffect(() => {
    	const debounceTimeout = setTimeout(() => {
        	return setQuery(debounceQuery);
        }, 100);
        
        return () => clearTimeout(debounceQuery);
    }, [debounceQuery]);
    
    return { query, debounceQuery, setDebounceQuery };
}

 

 

 

직접구현하는 throttle 

const [ throttle, setThrottle ] = useState(false);

const handleThrottle = () => {
	if(throttle) return;
    if(!throttle){
    	setThrottle(true);
        setTimeout(async () => {
        	doSomething();   //100ms마다 실행할 함수 
            setThrottle(false);
        }, 100);
    }
}

 

 

 

 

 

 

결론 

  • 북마크 연속 막기, 화면 리사이징 관련 이벤트, 연속 이벤트 막기하고 싶을 때는 " Debounce"
  • 무한 스크롤 이벤트과 같은 스크롤 이벤트는 " Throttle"
  • 역시 간단스기루하게 사용하고 싶다면 라이브러리 강추, 좀더 커스터마이징 하거나 작은 프로젝트에서 단순하게 사용하고 싶다면 setTimeout으로 직접 구현하는것이 오히려 더 가볍고 빠를 수도..!

 

 

 

[ 참고 ] 
Throttle, Debounce 차이점
- Throttle를 바닐라 자바스크립트, 그리고 리액트에서 구현하기