다음의 코드에서 문제가 되는 부분은 무엇일끼?
document.addEventListener('touchstart', handler, false);
touchstart에 대한 이벤트에서 options의 값을 false로 한것이다.
options는 false로 했기때문에 passive 옵션의 값도 false가 되고 이는 렌더링 퍼포먼스에 좋지 못하다.
addEventListener 를 사용하면,이벤트가 즉시 실행이 될까?🧐
답은 "passive의 옵션 값에 따라 다르다."이다.
이는 렌더러 프로세스와 관련있다.
렌러더 프로세스란 HTML,CSS,JS를 웹 페이지로 변환하는 과정으로,
기본적으로 모든 작업을 처리하는 Main thread와 Worker threads, Compositor thread, Raster thread 등이 존재한다.
thread | 작업 |
---|---|
Main | HTML 파싱, DOM/CSSOM 생성, 스타일 계산, 레이아웃 등의 작업을 수행하며, JavaScript 코드도 실행 |
Worker | ▪️ Main thread와 병렬로 동작하는 스레드로, 웹 워커나 서비스 워커와 같은 기능을 제공 ▪️ Worker threads는 Main thread의 부하를 줄이고, 백그라운드에서 복잡한 연산이나 네트워크 요청 등을 처리 |
Compositor | ▪️ 렌더링 과정 중 Paint(Rasterize)와 Composite 작업을 담당 ▪️ 화면의 스크롤이나 애니메이션과 같은 작업을 부드럽게 처리하기 위해 사용 |
Raster | Paint 작업의 일부를 담당하는 스레드로, Compositor thread가 결정한 화면의 일부 영역(타일)을 실제 픽셀로 변환하여 이를 Compositor thread에 넘겨줌 |
addEventListener에 등록된 이벤트는 렌더러 프로세스 중 Compositor thread에서 처리되며 Compositor thread는 해당 이벤트를 Main thread로 넘기고 Main thread에서 렌더트리를 넘겨받을때까지 기다린다.
그러나 여기에 핸들러를 실행하기 위해서는 복잡하거나 시간이 걸리는 Main thread의 작업을 기다려야하고, event.preventDefault가 실행되어서 터치나 스크롤등의 이벤트를 취소시킬 수 있다는 문제점이 있다.
이를 해결하기 위해서 addEventListener의 passive 값을 true로 설정해 passive를 활성화시키면 된다.
passive를 활성화 시키면, Main thread의 작업을 기다리지 않고 기다림 없이 이벤트 수신하는 즉시 핸들러가 작동하고 Paint,Composite 작업을 실행해 화면에 반영되어 렌더링 퍼포먼스가 향상되고 스크롤등의 퍼포먼스를 진행할때 방해를 받지 않게 된다.
이러한 이유로 addEventListener 에서 passive 옵션의 기본값은 false 이지만 Safari와 Internet Explorer를 제외한 브라우저에서는 wheel, mousewheel, touchstart, touchmove 이벤트에서의 기본 값은 true로 설정하고 있다.
그러나 성능 향상을 위해 passive:true를 사용할때, 주의할 점이 있다.
passive가 활성화되면 event.preventDefault를 사용할 수 없다는 점이다. event.preventDefault는 Main thread에서 진행되기 때문에, Main thread의 작업을 기다리지않는 passive 활성화 상태에서는 이를 사용할 수 없게 된다.