Frontend/React.js

[React] 이벤트 전파 방지

okojin 2025. 5. 11. 18:35

웹에서 특정 요소에서 이벤트가 발생하면 이벤트가 원하는 요소에 도달하기까지는 다음과 같은 과정을 거친다.

이벤트 전파 과정

 

먼저 캡처링 단계에서는 최상위 window 객체에서 문서 트리를 따라 하위 요소로 이벤트가 전파된다. 그리고 타깃 단계에서 이벤트의 발생원을 식별한다.

 

버블링 단계는 이벤트가 발생원에서 상위 요소로 전파되는 단계다. 최종적으로 최상위 window 객체에 도달하면 이벤트 전파가 종료된다.

 

정리하자면, 이벤트 처리는 이벤트 발생원에서만 실행되는 것이 아니다.

아래 예시 코드를 보면

export default function App() {
  const handleParent = () => alert('부모 요소');
  const handleCurrent = () => alert('현재 요소');
  const handleChild = () => alert('자식 요소');

  return (
    <div id='parent' onClick={handleParent}>
      부모 요소
      <div id='current' onClick={handleCurrent}>
        현재 요소
        <a id='child' href='https://www.google.com' onClick={handleChild}>
          자식 요소
        </a>
      </div>
    </div>
  );
}

다음과 같이 부모 요소 안에 현재 요소 안에 자식 요소가 있다고 가정했을 때, 자식 요소를 클릭하게 되면 다음과 같은 결과를 얻을 수 있다.

  1. alert 창 표시: 자식 요소
  2. alert 창 표시: 현재 요소
  3. alert 창 표시: 부모 요소
  4. 구글 페이지로 이동

이벤트 발생원을 기점으로 상위 요소를 향해 순차적으로 이벤트 핸들러가 실행되고 있다. 즉, 기본적으로 버블링 단계에서 이벤트가 처리되고 있다.

처리 순서 변경하기

버블링 단계가 아닌 캡처링 단계에서 이벤트를 처리할 수도 있다. 위의 예시코드를 다음과 같이 변경해보자

export default function App() {
  const handleParent = () => alert('부모 요소');
  const handleCurrent = () => alert('현재 요소');
  const handleChild = () => alert('자식 요소');

  return (
    <div id='parent' onClickCapture={handleParent}>
      부모 요소
      <div id='current' onClickCapture={handleCurrent}>
        현재 요소
        <a id='child' href='https://www.google.com' onClickCapture={handleChild}>
          자식 요소
        </a>
      </div>
    </div>
  );
}

이벤트 핸들러를 onClick에서 onClickCapture로 변경해주면 다음과 같은 결과를 얻을 수 있다.

  1. alert 창 표시: 부모 요소
  2. alert 창 표시: 현재 요소
  3. alert 창 표시: 자식 요소
  4. 구글 페이지로 이동

전파 방지

애초에 이벤트의 전파 자체를 방지하려면 다음과 같은 방법을 사용할 수 있다.

const handleChild = e => {
    e.stopPropagation();
    alert('자식 요소');
};

다음과 같이 e.stopPropagation()을 사용해주면 자식 요소에서 이벤트 버블링이 멈추게 되어 다음과 같은 결과를 얻을 수 있다.

  1. alert 창 표시: 자식 요소
  2. 구글 페이지로 이동

이벤트 기본 동작 취소하기

이벤트 기본 동작은 이벤트에 따라 브라우저에서 발생하는 동작을 말한다. 예를 들어 링크를 클릭하면 다른 페이지로 이동, 제출 버튼을 누르면 submit 양식 내용을 제출, 텍스트 상자에 키를 입력하면 해당 문자가 반영되는 등의 동작이 이에 해당한다.

이벤트 기본 동작은 이벤트 핸들러를 처리한 후 발생하게 되는데 이를 취소하는 것이 preventDefault 메서드의 역할이다.

const handleChild = e => {
    e.stopPropagation();
    alert('자식 요소');
};

다음은 실행 결과이다.

  1. alert 창 표시: 자식 요소
  2. alert 창 표시: 현재 요소
  3. alert 창 표시: 부모 요소

확실히 모든 전파를 마친 후 페이지가 이동하지 않는 것을 확인할 수 있다.

하지만 특정 이벤트에 따라 preventDefault 메서드로 취소할 수 없는 이벤트도 존재한다.