23/12/21 디바운싱

리액트로 디바운싱을 이해하려다가 머리 깨지는줄 알았다..
javasciprt로는 간단했다...
디바운싱이란
setTimeout의 비동기 특성을 이용하여 이벤트의 빈도를 제어하는 방식이다.
예로 입력필드가 있다고하면 onChange 나 addEventLiner로 매번 유효성검사를 하는건 자원적으로 매우 비효율 적일 것이다.
자동 검색어를 만든다고 가정하면 매 타이핑마다 계속 fetch..fetch.. 하면 자원적으로도 서버에 무리를 준다
사용자가 입력 후 최종적으로 1번 유효성 검사를 진행한다면 용자 UX적으로도 훌륭할 것이다.
아래는 간단한 Javasciprt 디바운싱 예제이다.
<input type="text" class="name">
<button disabled>button</button>
<script>
const inputName = document.querySelector('.name');
const btn = document.querySelector('button');
let deBounce;
inputName.addEventListener('input' , (e)=>{
if(deBounce){
clearTimeout(deBounce);
}
deBounce = setTimeout(()=>{
if(e.target.value.length > 5){
btn.disabled = false;
console.log('완료!');
}
},1000);
});
</script>
Button에 disabled를 하여 클릭 못하게 막고 name의 value가 5글자 이상일 경우에는 button이 클릭 가능하도록 변경하는 예제이다.
진행방식은 초기 이벤트리스너로 이벤트가 변경감지 deBounce 초기값은 undefined 이기에 doBounce에 setTimeout을 설정하는데 이때 저장하는 것은 setTimeout의 ID값이고 1000 / 1초 뒤에 실행 될것이다.
예로 마구잡이로 입력한다고하면 실행순서는 다음과 같다.
1. deBounce변수에 setTimeout 예로 ID값 1로 설정 태스크 큐에 등록
2. if는 1의 값이 있기에 True
3. clearTimeout 으로 큐에 있는 1의 setTimeout 작업을 삭제
4. deBounce setTimeout 예) ID 값 2 재할당
...반복
5. 최종 입력후 1초 뒤에 Button disabled = false로 변경하며 콘솔로그 출력
엄청 간단하다.
로그인 폼에 예로 사용자에게 알림표시까지 준다면 더 좋은 UX는 없을 것으로 생각이된다.
갑자기 요즘 공부하는 React에도 다시 반영을 하고 싶어졌다.
이전에 디바운싱으로 폼을 만들었지만 인간이라고 하는 동물은 지속적으로 잊어먹기 전에 해줘야 기억에 남는다는걸
React에서는 useEffect 사이트이펙트 관리 훅을 이용하여 구현하면 좋다
예로 useState에 input Value값을 넣어두고 이가 변경되면 useEffect가 변경되게 하고 클린업 함수로 이전의 함수를 정리하면 끝 !
리액트 디바운싱 예제
useEffect(()=>{
const deBounce = setTimeout(()=>{
setFormValid(inputValues.isIdValid && inputValues.isPasswordValid);
},1000);
return ()=>{
clearTimeout(deBounce);
console.log('클린업');
}
},[inputValues]);
클린업 함수는 두가지 개념을 알아야하는데
언마운트 시, 디펜던스 변경 시 useEffect를 실행하며 클린업함수도 변경이된다.
위 함수의 실행 컨텍스트는 다음과 같다.
1. 초기 랜더링시 inputValues에 initialData가 들어가게 되며, useEffect도 랜더링
2. deBounce 변수에 setTImeout의 ID값 설정 - 1000 / 1초 뒤에 설정 ****현재 ID값 1
3. 중요! 초기 랜더링 시에는 클린업함수가 실행되지 않는다. 왜냐? 초기랜더링시에는 리턴된 클린업 값이 없기에
그리고 클린업 함수를 내부에서 리턴한다.
4. 최초 입력 한다고 하면 deBounce에 ID값을 새로 배정한다. 예로 2
5. 이후 클린업 함수를 실행하는데 이는 이전의 리턴한 클린업함수를 실행하는것
렉시컬 환경은 클로저 즉 이전 기억을 가지고있는 클린업 함수를 실행시킨다
6. ID 1인 setTimeOut을 삭제시킨다.
이로써 최종적으로는 마지막으로 입력된 setTimeOut만 남아있게되는것이다.
난 이 Return 한다라는 것을 눈에 나중에 들어와서 엄청헷갈렸었다..
내 개념으로는 setTimeout이 태스크 큐에 반영되고 이후 clearTimeOut을 하면 태스크 큐에 반영되어 있는 작업을 바로 취소해야 하는 것이 아닌가 왜 이전을 취소하나 하고
알고보니 클린업함수는 클로저를 통해 이전의 렉시컬 환경을 기억하는 것이었다
난 이걸 이해하는데 3시간이 걸렸다...
'Web > Notepad' 카테고리의 다른 글
| [useQuery] StaleTime , gcTime (0) | 2024.03.21 |
|---|---|
| import BaseUrl 지정하기 (0) | 2024.03.14 |
| [MySQL] CRUD / 오름 내림차순 (0) | 2024.02.13 |
| 23/12/25 Auth (0) | 2023.12.26 |
| 23/12/15 React - 상태 개념 (0) | 2023.12.15 |