스크롤 기능을 막아야하는 상황에서 대부분은 body 에
overflow-y: hidden
을 주는 방법이 제시되지만, 그렇지 않은 경우 자바스크립트로 이를 처리해야한다.
처음엔 아래와 같이 이벤트를 주었지만 작동하지 않았다 ㅠ
$body.addEventListener('scroll', function(e) {
e.preventDefault();
})
두번째 시도로 아래와 같이 다른 이벤트에도 적용해보았지만 작동은 하지 않고 에러까지 발생했다.
const $body = document.querySelector('body');
function preventScroll(e) {
e.preventDefault();
}
$body.addEventListener('scroll', preventScroll);
$body.addEventListener('touchmove', preventScroll);
$body.addEventListener('mousewheel', preventScroll);
구글링을 해보니 passive: false
옵션을 추가해주면 된다고 한다. 그런데 mousewheel
이벤트와 같이 스크롤과 관련된 이벤트는 기본적으로 passive
로 처리되어 추가 옵션을 설정할 수 없었다.
대신, wheel
이벤트를 사용하여 스크롤을 감지하고 preventDefault
를 호출하면서 성능 최적화와 문제 해결을 동시에 할 수 있었다.
const $body = document.querySelector('body');
function preventScroll(e) {
e.preventDefault();
}
// 'wheel' 이벤트를 사용하여 스크롤 감지 후 방지
$body.addEventListener('wheel', preventScroll, { passive: false });
$body.addEventListener('click', function() { // body 를 다시 클릭하면 스크롤 재개
$body.removeEventListener('wheel', preventScroll, { passive: false });
});
passive
옵션을 추가하고 wheel
이벤트로 바꾸었더니 body 스크롤링이 잘 멈추었다.
wheel
이벤트와 scroll, mousewheel
의 차이, 그리고 성능최적화에 대한 내용이 더 궁금하여 챗지피티에 물어보니, 내용은 다음과 같았다.
wheel
이벤트는 마우스 휠 또는 트랙패드 등 더 다양한 입력 장치에서 발생하는 스크롤 이벤트로, mousewheel
이벤트와 비슷하지만wheel
이벤트가 표준에 더 가깝고 여러 입력 장치에서의 일관성을 제공한다고 한다.
또 wheel
이벤트가 passive
로 처리되는 것은 브라우저가 성능 최적화를 위해 도입한 개념 중 하나이고, 브라우저는 기본적으로 wheel
이벤트에 대해 passive
플래그를 설정하기 때문에 이벤트 리스너 내에서 preventDefault
를 호출하지 못하게 한다.
passive
플래그가 설정된 이벤트 리스너에서 preventDefault
를 호출하는 것은 브라우저가 스크롤링 동작을 최적화하기 위해 이벤트 핸들러를 비동기적으로 실행하도록 허용하게 되는데, 이로 인해 호출 순서가 보장되지 않기 때문에 스크롤을 막아야 하는 경우에는 passive: false
로 설정된 이벤트 리스너를 사용해야 한다..!