-
[ React ] 과도한 이벤트 핸들러 호출 방지 throttling & debouncingTIL 2024. 2. 23. 23:23728x90
Throttling & Debouncing 이란?
짧은 시간 간격으로 연속해서 이벤트가 발생할 때 과도한 이벤트 핸들러 호출을 방지하는 기법이 바로 쓰로틀링과 디바운싱이다.
Throttling 의 예시 이미지
타입 1 : Leading Edge 타입 2 : Trailing Edge 타입 3 : Leading & Trailing edge 짧은 시간 간격으로 연속해서 발생한 이벤트들을 일정시간 단위(delay)로 그룹화하여
처음 또는 마지막 이벤트 핸들러만 호출되도록 하는 것이다.
주로 사용되는 예 : 무한 스크롤
Debouncing 의 예시 이미지
출처 : 자바스크립트 딥다이브 짧은 시간 간격으로 연속해서 이벤트가 발생하면 이벤트 핸들러를 호출하지 않다가
마지막 이벤트로부터 일정시간(delay)이 경과한 후에 한 번만 호출되도록 하는 것.
주로 사용되는 예 : 입력값 실시간 검색, 화면 resize 이벤트
메모리 누수 (Memory Leak)란?
필요하지 않은 메모리를 계속 점유하고 있는 현상을 말한다.
Q. setTimeout이 메모리 누수를 유발하는가?
상황에 따라 누수를 일으킬 수도, 아닐 수도 있다.
하나의 페이지에서 페이지 이동 없이 setTimeout을 동작시키고 타이머 함수가 종료될 때까지 기다린다면 메모리 누수는 없다.
리액트로 만든 SPA 웹사이트는 페이지 이동 시 컴포넌트가 언마운트 된다.
그런데 페이지 이동 전에 setTimeout으로 인해 타이머가 동작중인 상태에서 clearTimeout을 안해주고 페이지에 이동시 컴포넌트는 언마운트 되었음에도 불구하고 타이머는 여전히 메모리를 차지하고 동작하고 있다. 이 경우는 메모리 누수에 해당한다고 말할 수 있다.
Throttling & Debouncing 의 예시 code.
import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; export default function Home() { const navigate = useNavigate(); let timerId = null; // Leading Edge Throttling const throttle = (delay) => { if (timerId) { // timerId가 있으면 바로 함수 종료 return; } console.log(`API요청 실행! ${delay}ms 동안 추가요청 안받음`); timerId = setTimeout(() => { console.log(`${delay}ms 지남 추가요청 받음`); // alert("Home / 쓰로틀링 쪽 API호출!"); timerId = null; }, delay); }; // Trailing Edge Debouncing const debounce = (delay) => { if (timerId) { // 할당되어 있는 timerId에 해당하는 타이머 제거 clearTimeout(timerId); } timerId = setTimeout(() => { // timerId에 새로운 타이머 할당 console.log(`마지막 요청으로부터 ${delay}ms지났으므로 API요청 실행!`); timerId = null; }, delay); }; useEffect(() => { return () => { // 페이지 이동 시 실행 if (timerId) { // 메모리 누수 방지 clearTimeout(timerId); } }; }, [timerId]); return ( <div style={{ paddingLeft: 20, paddingRight: 20 }}> <h1>Button 이벤트 예제</h1> <button onClick={() => throttle(2000)}>쓰로틀링 버튼</button> <button onClick={() => debounce(2000)}>디바운싱 버튼</button> <div> <button onClick={() => navigate("/company")}>페이지 이동</button> </div> </div> ); }
728x90'TIL' 카테고리의 다른 글
[ TypeScript ] React + Vite 로 시작하는 TypeScript (0) 2024.03.04 [ React ] 공통된 로직, 기능을 깔끔하게! " Custom Hooks " (0) 2024.02.28 [ React ] 쉽고, 직관적인 React Query (0) 2024.02.22 [ React ] 리덕스 미들웨어 - Redux Thunk (1) 2024.02.20 [ React ] axios , json-server 를 이용한 통신 실습 (0) 2024.02.19