
모바일 웹뷰에서 터치 이벤트를 처리하다가 콘솔을 확인했더니 아래와 같이 무수히 많은 경고 로그창이 발생된것을 발견했습니다. 동작에는 큰 사이드 이펙트는 없었지만 추후 문제가 발생할 수 있을 것 같아 해결하고 넘어가는것을 목표로 삼았습니다.
이 경고가 발생하는 이유를 우선 생각해보겠습니다.
해석하자면
수동 이벤트 리스너 호출 내부에서 preventDefault를 사용할 수 없다. 로 볼 수 있습니다.
const onHandleTouchStart = (e) => {
e.preventDefault();
...
...
}
<Canvas onTouchStart={onHandleTouchStart}>
제가 작성한 코드는 위와 비슷하고 이벤트의 기본 동작을 막기 위해 preventDefault() 함수를 호출하였습니다.
touchstart의 이벤트에서 호출하면 브라우저의 기본 스크롤 동작을 막는 것이죠.
passive 옵션은 이벤트 리스너를 추가할 때 addEventListener의 옵션 중 세번 째 인자로 전달하는 객체 속성 중의 하나입니다.
이를 true로 설정하면 해당 이벤트 리스너는 이벤트의 기본 동작을 막지 않을 것을 브라우저에게 알리는 것입니다.
모바일 환경에서 성능을 최적화하기 위해서 최신 웹 브라우저들은 암묵적으로 passive true로 기본값을 적용하는 이벤트들이 있습니다.
바로 스크롤과 관련된것이죠.
그럼 어떤 이벤트들이 존재할까요?
| 이벤트 (Event) | 기본 passive 값 (Default) | 주요 목적 및 영향 |
|---|---|---|
touchstart | true | 터치 시작. 스크롤이나 확대/축소의 시작점이 될 수 있음. |
touchmove | true | 터치 이동. 스크롤 동작과 직접적으로 연관됨. |
wheel | true | 마우스 휠 스크롤. 데스크톱 환경의 스크롤에 영향. |
mousewheel | true | 마우스 휠 스크롤. 지원 중단. 일부 브라우저에서는 지원. |
그렇다면 왜 스크롤과 관련된 이벤트들을 true로 설정하게 되었을까 의문점이 듭니다.
사용자가 터치를 했을 때 preventDefault()를 호출하여 스크롤을 막을지 말 지 브라우저는 기다려야 했고 이 짧은 대기 시간이 스크롤 동작을 지연시키고 버벅이는 현상 저하가 발생할 가능성이 높기 때문입니다.
만일 preventDefault()함수가 필요한 경우에는 이벤트를 어떻게 등록해야 할까요?
바로 이벤트를 등록할 때 passive false로 명시하면 됩니다.
브라우저의 기본 스크롤 동작을 막고 커스텀 동작이 필요하다면
element.addEventListener('touchstart', onHandleTouchStart, { passive: false });
위 코드 처럼 명시적으로 작성하면 됩니다. 다만, 꼭 필요한 경우에만 사용 해야 합니다.
또 preventDefault() 함수가 필요 없다면 이벤트 등록 시 브라우저가 내부적으로 passive true로 처리하기 때문에 명시하지 않아도 됩니다.
PC 웹 사이트를 만들때와 달리 모바일까지 고려하는 경우에 다양한 이벤트들이 존재하므로 이벤트 등록 후 사용할 때 항상 이 부분을 짚고 넘어가는것이 추후 유지보수에 유용할 듯 합니다.