요약

기준이벤트 버블링이벤트 캡처링
전파 방향자식 요소에서 시작해 부모 요소로 이동최상위 요소에서 시작해 목표 요소(이벤트가 발생한 요소)로 이동
사용 목적하위 요소에서 발생한 이벤트를 상위 요소에서 처리할 수 있게 함상위 요소에서 하위 요소로 이벤트를 전달하기 전에 미리 처리할 수 있게 함
기본 동작기본적으로 활성화되어 있음명시적으로 설정해야 활성화됨 (addEventListener의 세 번째 인자로 true 설정)
주 사용 사례이벤트 위임과 같이 여러 자식 요소에 공통적인 이벤트 핸들러를 적용할 때 유용특정 이벤트를 가로채서 특별한 처리를 하기 전에 미리 캡처링할 때 유용
중단 방법stopPropagation() 메서드를 사용하여 이벤트 버블링 중단stopPropagation() 메서드를 사용하여 이벤트 캡처링 중단
주의 사항부모 요소에 이벤트가 전달되기 때문에 불필요한 이벤트 처리가 발생할 수 있음캡처링 단계에서 이벤트를 처리하면 하위 요소에서는 이벤트를 감지할 수 없게 될 수 있음

이벤트의 캡처링, 버블링, 위임을 왜 알아야 할까?

  • 사용자와의 상호작용을 위해 다양한 이벤트 리스너를 추가하다보면 이벤트가 계획대로 동작하지 않을 때가 있다.
  • 이벤트의 동작 방식에 대해 알고 적절한 구조로 요소에 이벤트를 할당해야 문제를 해결 할 수 있다.

이벤트 버블링

정의

  • 특정 DOM 요소에서 이벤트가 발생했을 때, 이벤트가 부모 요소로 전달되며 최상위 요소까지 계속 전달되는 현상을 말한다.

예제 코드로 동작을 확인하기

  • 버블링은 이벤트 리스너의 기본값이므로 특별히 작성해야 할 문법은 없다.
<!DOCTYPE html>
<html>
<head>
    <title>이벤트 버블링 예제</title>
</head>
<body>

<div id="parent" style="width: 200px; height: 200px; background-color: #f2f2f2;">
    부모
    <div id="child" style="width: 100px; height: 100px; background-color: #a1a1a1; margin-top: 20px;">
        자식
    </div>
</div>

<script>
    // 부모 요소에 이벤트 리스너 추가

    document.getElementById('parent').addEventListener('click', function(event) {
        alert('부모 요소가 클릭되었습니다. 이벤트 발생 요소: ' + event.target.id);
    });

    // 자식 요소에 이벤트 리스너 추가
    document.getElementById('child').addEventListener('click', function(event) {
        alert('자식 요소가 클릭되었습니다.');
    });
</script>

</body>
</html>
  • 자식 요소를 클릭한 경우
    • 자식 요소의 이벤트 실행 ⇒ 부모 요소의 이벤트 실행
  • 부모 요소를 클릭한 경우
    • 부모 요소의 이벤트 실행
  • 두 경우를 비교해보면 이벤트가 발생한 요소에서 상위 요소로 전파되는 것을 확인할 수 있다.
  • 전파되는 이벤트를 감지하려면 이벤트 유형이 같아야 한다.
    • 부모 요소의 이벤트 유형이 ‘click’이 아니라 다른 유형이라면 이벤트는 동작하지 않는다.

이벤트 버블링 사용 예시

하위 요소에서 발생하는 이벤트를 감지할 때

  • 사용자가 화면을 클릭 했을 때 감지하고 싶은 정보
    • 클릭한 요소
    • 클릭한 위치(좌표)
  • document에 이벤트 리스너를 추가해서 문서 하위 요소에서 발생한 이벤트가 전파되는 것을 감지하여 원하는 정보를 알 수 있다.

이벤트 캡처링

정의

  • 이벤트가 최상위 요소에서 시작하여 이벤트가 발생한 DOM 요소까지 내려가는 현상이다.

문법

  • 이벤트 리스너에 3번째 인자로 true를 입력해야 한다.
document.getElementById('parent').addEventListener('click', function() {
    console.log('부모에서 캡처링');
}, true); 
  • 이벤트 캡처링은 이벤트 순서를 세밀하게 조절해야하는 경우에 사용되고 보통 버블링으로 해결할 수 있다.

예제 코드로 동작을 확인하기

  • 앞의 버블링 예제 코드에서 부모 요소의 이벤트 리스너에 3번째 인자로 true 입력
<!DOCTYPE html>
<html>
  <head>
    <title>이벤트 버블링 예제</title>
  </head>
  <body>
    <div
      id="parent"
      style="width: 200px; height: 200px; background-color: #f2f2f2"
    >
      부모
      <div
        id="child"
        style="
          width: 100px;
          height: 100px;
          background-color: #a1a1a1;
          margin-top: 20px;
        "
      >
        자식
      </div>
    </div>

    <script>
      // 부모 요소에 이벤트 리스너 추가

      document.getElementById("parent").addEventListener(
        "click",
        function (event) {
          alert(
            "부모 요소가 클릭되었습니다. 이벤트 발생 요소: " + event.target.id
          );
        },
        true
      );

      // 자식 요소에 이벤트 리스너 추가
      document
        .getElementById("child")
        .addEventListener("click", function (event) {
          alert("자식 요소가 클릭되었습니다.");
        });
    </script>
  </body>
</html>
  • 부모 요소를 클릭한 경우
    • 부모 요소의 이벤트가 동작
  • 자녀 요소를 클릭한 경우
    • 부모 요소 이벤트 동작 ⇒ 자녀 요소 이벤트 동작
  • 캡처링을 true로 설정한 이벤트 리스너가 먼저 감지하는 흐름은 알 수 있지만 좀 더 자세히 알아야 할 것이 있다.

이벤트 발생 순서 (캡처링 ⇒ 타겟 ⇒ 버블링)

  • 이벤트는 캡처링이 실행되고 타겟까지 도달한 다음 버블링된다.
  • 순서 상 캡처링이 먼저 동작하는데 캡처링 true인 이벤트 리스너가 있으면 첫번째 단계에서 이벤트를 감지하는 것이다.
  • 즉, 모든 이벤트는 캡처링, 타겟, 버블링 순서로 실행이 되는데 옵션에 따라 어느 이벤트를 감지할지를 선택할 수 있는 것이다.
  • 부모 요소의 이벤트 리스너가 캡처링을 감지하겠다고 설정해뒀기 때문에 자식 요소의 이벤트가 동작할 때 캡처링 단계에서 부모 요소가 감지하고 타겟 단계에서 해당 자녀 요소가 이벤트를 감지하는 것이다.

버블링과 캡처링 차단하기

stopPropagation() : 이 메서드를 이벤트 처리 함수 내에서 호출하면, 해당 이벤트의 콜백을 실행한 뒤 이후에 진행되는 버블링과 캡처링이 중단된다. 이를 통해 불필요한 이벤트 전파를 방지할 수 있다. 이벤트 발생 순서의 흐름을 차단하는 것이다.

이벤트 위임

이벤트 위임이란?

  • 이벤트가 전파되는 특징을 활용하는 방법이다.
  • 다른 요소에서 발생한 이벤트를 감지하여 대신 콜백을 실행하는 구조이다.

이벤트 위임의 장점

  • 코드의 간결성
  • 메모리 사용 최적화
  • 동적 요소에 대한 이벤트 핸들링

예제 코드로 이벤트 위임 동작 확인하기

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Event Delegation Example</title>
    <style>
      /* 타겟 범위를 확인하기 위한 표시 */
      li {
        border: 1px solid red;
        cursor: pointer;
      	margin: 10px;
      }
    </style>
  </head>
  <body>
    <ul id="itemsList">
      <li>아이템 1</li>
      <li>아이템 2</li>
      <li>아이템 3</li>
      <li>아이템 4</li>
    </ul>

    <script>
      // 이벤트 위임을 사용하여 UL 요소에 이벤트 리스너를 추가합니다.
      document
        .getElementById("itemsList")
        .addEventListener("click", function (event) {
          // event.target은 클릭된 요소입니다.
          // 이 예제에서는 LI 요소가 클릭되면 그 요소에 대한 정보를 가져옵니다.
          if (event.target.tagName === "LI") {
            // 태그 이름이 LI인지 확인합니다.
            alert(event.target.textContent + "가 클릭되었습니다.");
          }
        });
    </script>
  </body>
</html>
  • event.target으로 이벤트가 발생한 타겟을 참조할 수 있다.
  • 이벤트 리스너는 id가 itemsList인 요소에 추가됐지만 하위 요소를 클릭하면 이를 감지하여 동작한다.
  • item 하나씩 이벤트 리스너를 추가할 필요가 없는 것이다.

참고자료 : https://poiemaweb.com/js-event#6-이벤트의-흐름

profile
문제를 컴퓨터로 해결하는 데서 즐거움을 찾는 프론트엔드 개발자

0개의 댓글