-
Notifications
You must be signed in to change notification settings - Fork 0
⏰ 디바운스와 쓰로틀링
현재 채팅 기능에서 새로운 메시지가 수신될 때
- 사용자가 채팅의 상단(이전 채팅 기록)을 보고 있다면 → 계속 상단에 위치
- 사용자가 채팅의 최하단(최신 채팅 기록)을 보고 있다면 → 계속 하단으로 이동 (새로운 메시지가 수신되면 스크롤을 아래로 이동시켜 최신 채팅이 가장 아래에 위치하도록)
위의 동작을 수행한다.
이에 따라, 현재 사용자가 스크롤 할 때 스크롤의 위치를 알고 있을 필요가 있었다.
사용자의 스크롤이 현재 어떤 위치에 있는지 파악하기 위해 onScroll
이벤트를 활용했으며 이벤트 발생에 따라 스크롤이 된 비율을 state로 관리하게 되었다.
const handleScroll = () => {
if (!messageAreaRef.current) return;
const { scrollTop, clientHeight, scrollHeight } = messageAreaRef.current;
setScrollRatio(((scrollTop + clientHeight) / scrollHeight) * 100);
};
위 코드의 문제는 사용자가 스크롤 할 때 마다 이벤트가 매우 자주 발생하는 것이다.
사진에서 볼 수 있듯 스크롤을 하는 과정에서 매우 많은 이벤트가 발생하는 것을 볼 수 있다.
성능 저하가 우려되는 상황이므로 다른 방법이 필요했다.
💡 연속으로 호출되는 함수들 중 마지막에 호출되는 함수(또는 제일 처음 함수)만 실행되도록 하는 것디바운싱은 화면의 resize 등에서 활용할 수 있다.
resize에 따라 수행되는 로직이 있다면 화면이 resize되는 동안 이벤트가 계속해서 발생하고 이는 성능 저하를 일으킬 수 있다.
따라서, 이벤트가 계속해서 실행되지 않도록 설정해줄 필요가 있다.
이에 따라 일정 시간 동안 입력이 없는 경우 원하는 동작을 완료했다고 판단하고 로직을 수행하도록 설정해야 한다.
let timer;
document.querySelector('#div').addEventListener('resize', () => {
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
// 수행할 행동
}, 200);
});
위의 내용을 활용하여 AJAX 검색에도 적용할 수 있다.
💡 마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 것디바운싱과 유사하지만 마지막 이벤트만 발생하는 디바운싱과 달리 일정한 주기로 계속해서 이벤트가 발생한다는 차이점이 있다.
쓰로틀링은 일정 주기마다 정해진 동작을 수행하기에 디바운스에 비해 조금 더 세밀하게 제어할 수 있다고 볼 수 있다.
let timer;
document.querySelector('#div').addEventListener('scroll', () => {
if (!timer) {
timer = setTimeout(() => {
timer = null;
// 수행할 행동
}, 200);
}
});
쓰로틀링 스크롤 이벤트에서 대표적으로 활용된다.
현재 상황에서 필요한 것은 쓰로틀링이다.
스크롤 이벤트가 너무 자주 발생하기 때문에 적절히 제한해야 하며, 스크롤이 되는 중에 새로운 메시지가 오는 경우도 있기 때문이다.
만약, 디바운스를 적용한다면 스크롤이 모두 끝나야 이벤트가 발생하기 때문에 스크롤 전과 후의 공백기간이 길어지게 되며 이때 메시지가 수신된다면 의도하지 않은 결과가 발생할 수 있다.
따라서, 쓰로틀링을 적용하여 일정 주기로 현재 위치를 저장할 필요가 있다.
const handleScroll = () => {
if (!timer) {
timer = setTimeout(() => {
timer = null;
if (!messageAreaRef.current) return;
const { scrollTop, clientHeight, scrollHeight } = messageAreaRef.current;
setScrollRatio(((scrollTop + clientHeight) / scrollHeight) * 100);
}, 500);
}
};
위의 과정을 통해 불필요한 계산을 줄이고 사용자의 스크롤에 따른 스크롤 위치 변화를 저장할 수 있게 되었다.