본문 바로가기
Javascript

[JS] event.stopPropagation()의 위험성

by F.E.D 2022. 12. 25.

이벤트 전파를 막기 위해서 event.stopPropagation()을 많이 사용하곤 합니다.

주로, 모달과 같은 대화 상자를 만들 때 dimmed 영역(흐린 배경 영역)을 클릭하여 해당 모달을 감추고 싶은데, 그 영역을 포함하고 있는 컨텐츠를 클릭했을 때 이벤트 전파를 통해서 의도치 않게 닫혀버릴 때 사용할 수 있습니다.

document.querySelector('html').addEventListener('click', () => {
   // 모달을 닫기
});

document.querySelector('#someMenus')?.addEventListener('click', (event) => {
  event.stopPropagation();
  // 해당 요소 내부에는 도달하지 않도록 합니다.
});

당장은 이러한 조치가 좋아보일 수 있으나, 위임을 html에 한다는 것은 매우 위험한 발상입니다.

document 또는 html, body 등 최상위에 위임을 한다는 것은 나중에 대처할 일에 대한 예상 범위를 넘어설 수 있습니다.

jquery에서 return falseevent.preventDefault()event.stopPropgation()을 반환하지만, 일반적인 javascript에서는 일어나지 않습니다.

 

이벤트 전파 중지는 이벤트 취소와 같이 생각해야 하며, 해당 의도로만 사용되어야 합니다.

form 요소의 submit을 방지하거나 페이지 영역에 대한 포커스를 허용하지 않으려는 경우, DOM의 상위에 등록된 원하지 않는 이벤트 핸들러가 있기 때문이 아니라 이벤트 발생을 원하지 않기 때문에 전파를 중지합니다.

클릭 이벤트를 완전히 제거하는게 아니라, 페이지에서 다른 코드가 실행되는 것을 방지하기 위함입니다.

 

따라서 더 나은 옵션은 다음과 같습니다.

document.addEventListener('click', (event) => {
  if(!event.target.closest('#container')?.length) {
    console.log('메뉴 가리기');
  }
})

 

event preventDefault()에 대해서도 좀 더 나은 위임방식이 있습니다.

document.addEventListener('click', (event) => {
  if(event.defaultPrevented) return;
  
  if(this.hostname !== 'css-tricks.com') {
    // ga 호출 등
    console.log('ga호출');
  }
})

event.defaultPreventeda 링크를 클릭하는 것에 대해서 event.preventDefault()하고 사용한 다른 이벤트 들에 대해서 예외처리를 할 수 있습니다.

따라서, a링크를 통한 실제 링크에 대해서만 따로 검증할 수 있게 되는 것입니다.

 

fin.

 

 

출처 : https://css-tricks.com/dangers-stopping-event-propagation/

댓글