브라우저에서 동작하는 js의 이벤트를 최적화 하기 위한 방법

담당
황찬우
완료
완료
유형
JavaScript
비고

요약


js 이벤트 최적화 방법
  • 이벤트 위임 (Event Delegation): 하나의 이벤트 핸들러를 사용하여 여러 이벤트를 효율적으로 처리하며, 불필요한 이벤트 핸들러 생성을 방지하여 메모리 사용을 최적화합니다.
  • 잔류 핸들러 제거: 요소가 제거되더라도 이벤트 핸들러가 메모리에 남을 수 있으므로, 요소 제거 시 잔류 핸들러를 직접 제거하거나 페이지를 떠날 때 모든 잔류 핸들러를 제거하는 것이 좋습니다.
  • Throttle와 Debounce: 스크롤 및 리사이즈 이벤트와 같이 자주 발생하는 이벤트를 제어하기 위해 throttle와 debounce를 사용하여 함수 호출 빈도를 제어하고 성능을 최적화합니다.
  • requestAnimationFrame (rAF): 스크롤 이벤트를 최적화하고 부드러운 스크롤 처리를 도와주며, 브라우저의 렌더링 주기에 맞춰 이벤트를 트리거합니다.
  • Passive Event: 스크롤 등의 이벤트를 부드럽게 처리하기 위해 passive 이벤트를 사용하여 preventDefault 호출을 최적화합니다.
  • setTimeout 메소드 활용: 리사이즈 이벤트와 같이 브라우저 과부하를 방지하기 위해 setTimeout 메소드를 활용하여 이벤트를 최적화합니다.
 

js 이벤트 최적화


 

이벤트 위임(Event Delegation)

  • 하나의 이벤트 핸들러를 사용하여 여러 이벤트를 효율적으로 처리할 수 있다.
  • 불필요한 이벤트 핸들러의 생성을 방지하고 메모리 사용을 최적화할 수 있습니다.
 

더 이상 필요하지 않은 이벤트 핸들러(잔류 핸들러) 제거하기

  • 요소가 제거되지만 이벤트 핸들러는 남아서 메모리를 점유하는 경우가 있습니다.
  • 요소 제거시 잔류 핸들러를 직접 제거하거나, 페이지를 떠나기 전 onunload 이벤트 핸들러를 이용하여 잔류 핸들러를 모두 제거하는 편이 좋습니다.
 

throttle와 debounce

throttle
  • 특정 함수의 호출 횟수를 줄여, 웹 성능이 저하되는 것을 방지하는 방법
  • 마지막 함수가 호출된 후 일정 시간이 지나기 전에는 다시 호출되지 않도록 한다.
  • 일정 주기(밀리 초)마다 정기적으로 기능 실행을 보장한다.
  • 스크롤 이벤트를 이용하게 되면 throttle 함수를 이용해 이벤트가 트리거 되는 텀을 조정하는 방법으로 사용할 수 있다.
window.addEventListener('scroll', throttle(onScroll, 300))
debounce
  • 특정 함수의 호출 횟수를 줄여, 웹 성능이 저하되는 것을 방지하는 방법
  • 이벤트를 그룹화하여 특정시간이 지난 후 하나의 이벤트만 발생시킨다.
  • 스크롤 이벤트에서 스크롤할 때마다 실행되는 이벤트를 설정한 주기마다 실행되게 할 수 있다.
  • 리사이즈 이벤트를 이용하게 되면 debounce 함수를 이용하여 이벤트가 완료되고 나면 실행되도록 최적화한다.
throttle와 debounce 문제점
throttle 함수는 debounce를 기반으로 동작하고, debounce는 setTiemout을 기반으로 동작한다. 즉 둘 다 setTimeout이라는 Web API에 의해 실행되는데 이는 정확한 지연 시간을 보장해주지 않기 때문에 기대한 결과대로 동작하지 않을 수 있다.
 

requestAnimationFrame(rAF)

  • 스크롤 이벤트가 너무 자주 발생하는 것을 방지하고, 브라우저가 렌더링 할 수 있는 만큼의 스크롤 이벤트 구현이 완성되어 부드럽고 최적화된 스크롤 처리를 하게 돕는 방법
  • 브라우저가 렌더링 할 수 있는 능력(브라우저는 60fps로 화면을 렌더링함)에 맞춰 이벤트를 트리거해줄 수 있습니다.
  • setTimeout, setInterval은 화면에 해당 요소가 안 보여도 무조건 콜백 함수가 호출되지만, rAF는 화면에 요소가 보이지 않을 시 콜백 함수가 호출되지 않는다.
  • rAF에 콜백을 넘겨주면 브라우저가 화면을 다시 그리기 전에 해당 함수를 호출합니다.
  • 실제로 호출되어야 하는 콜백 함수가 rAF에 의해 비동기로 처리되고, tick에 의해 브라우저 렌더링 범위 내에서 animation frame에 들어가게 되므로 스크롤 이벤트를 최적화할 수 있습니다.
export function toFitSimple(cb) { let tick = false return function trigger() { if (tick) { return } tick = true return requestAnimationFrame(function task() { tick = false return cb() }) } }
 

Passive Event

  • 스크롤 시 바로 화면을 합성하도록 하여 부드러운 스크롤이 동작하게 돕는 방법
  • 브라우저는 기본적으로 preventDefault를 호출하는지 여부를 감시하게 된다. 스크롤 이벤트를 호출할 경우에는 event 객체의 preventDefault를 호출하지 않기 때문에 이 비용을 절감할 수 있습니다.
  • passive 속성을 true로 지정해줄 경우, preventDefault API를 호출하지 않음을 명시하여 event.preventDefault가 호출되는지에 대한 감시 비용을 줄일 수 있다.
document.addEventListener('scroll',onScroll,{passive:true});
 

eventListener에 setTimeout 메소드 사용

  • window의 resize 이벤트를 그대로 사용하면 브라우저창 리사이징시마다 콜백 코드가 실행된다.
  • 매 resize마다 코드를 실행해야 하는 경우 매우 비효율적이고 브라우저에 과부하를 줄 수 있기 때문에, 의도적이지 않은 경우에는 setTimeout 메소드를 사용하면 좋다.
// 최적화 전 window.addEventListener('resize', function(){}); // 최적화 후 let delay = 300; let timer = null; window.addEventListener('resize', function(){ clearTimeout(timer); timer = setTimeout(function(){}, delay); });
 
 

참고 사이트