[JavaScript] 웹 인터랙션의 핵심, JavaScript 이벤트 버블링과 캡처링

웹 페이지에서 버튼을 클릭하거나 키보드를 누르는 등 사용자의 모든 행동은 **이벤트(Event)**로 감지됩니다. JavaScript는 addEventListener를 통해 이러한 이벤트를 처리하는데, 하나의 이벤트가 발생했을 때 여러 요소가 중첩되어 있다면 어떤 순서로 이벤트가 전달될까요? 이 이벤트 전파 방식을 이해하는 데 핵심적인 개념이 바로 **이벤트 버블링(Bubbling)**과 **캡처링(Capturing)**입니다. 👂

1. 이벤트 흐름의 3단계

DOM에서 이벤트가 발생하면, 이벤트는 다음과 같은 3단계의 흐름을 거칩니다.

  1. 캡처링 단계 (Capturing Phase): 이벤트가 최상위 window 객체에서 시작하여 이벤트가 발생한 대상 요소(target element)까지 하위로 전파됩니다.
  2. 타겟 단계 (Target Phase): 이벤트가 실제 대상 요소에 도달하여 해당 요소에 등록된 이벤트 리스너가 실행됩니다.
  3. 버블링 단계 (Bubbling Phase): 이벤트가 대상 요소에서 시작하여 다시 최상위 window 객체까지 상위로 전파됩니다.

2. 이벤트 버블링 (Event Bubbling)

버블링은 마치 물속의 거품이 수면으로 올라오는 것처럼, 이벤트가 가장 안쪽 요소에서 시작하여 바깥쪽 부모 요소들로 퍼져나가는 방식입니다. 대부분의 브라우저는 기본적으로 이 버블링 방식을 따릅니다.

  • 동작 예시: <p> 태그가 <div> 안에 있고, <div><body> 안에 있을 때 <p>를 클릭하면, 이벤트는 <p><div><body><html>documentwindow 순서로 전파됩니다.
<div id="outer">
  Outer
  <div id="inner">Inner</div>
</div>
const outer = document.getElementById('outer');
const inner = document.getElementById('inner');

outer.addEventListener('click', () => console.log('Outer Div Clicked (Bubbling)'));
inner.addEventListener('click', () => console.log('Inner Div Clicked (Bubbling)'));

// Inner Div를 클릭하면 콘솔에 아래 순서로 출력됨:
// 1. Inner Div Clicked (Bubbling)
// 2. Outer Div Clicked (Bubbling)

3. 이벤트 캡처링 (Event Capturing)

캡처링은 버블링과 정반대로, 이벤트가 최상위 요소에서 시작하여 실제 이벤트 대상까지 내려가는 방식입니다. 이 방식은 기본적으로 사용되지 않지만, addEventListener의 세 번째 인자를 true로 설정하여 활성화할 수 있습니다.

// addEventListener(type, listener, useCapture)
outer.addEventListener('click', () => console.log('Outer Div Clicked (Capturing)'), true);
inner.addEventListener('click', () => console.log('Inner Div Clicked (Capturing)'), true);

// Inner Div를 클릭하면 콘솔에 아래 순서로 출력됨:
// 1. Outer Div Clicked (Capturing)
// 2. Inner Div Clicked (Capturing)

4. 이벤트 위임 (Event Delegation)

버블링의 특성을 활용한 매우 유용한 패턴이 이벤트 위임입니다. 하위의 여러 요소에 각각 이벤트 리스너를 다는 대신, 그들의 공통된 부모 요소에 하나의 리스너만 등록하는 방식입니다. 이를 통해 동적으로 추가되는 요소에도 이벤트를 적용할 수 있고, 메모리 사용을 줄여 성능을 향상시킬 수 있습니다.

// ul#itemList의 각 li에 리스너를 다는 대신, 부모인 ul에 하나만 등록
document.getElementById('itemList').addEventListener('click', function(event) {
  // 클릭된 요소가 LI 태그인지 확인
  if (event.target && event.target.tagName === 'LI') {
    console.log('Clicked item:', event.target.textContent);
  }
});

요약 및 정리

이벤트 버블링과 캡처링은 DOM 이벤트의 전파 방식을 설명하는 핵심 모델입니다.

  • 캡처링: 이벤트가 위에서 아래로 전파되는 단계.
  • 버블링: 이벤트가 아래에서 위로 전파되는 단계. (기본 동작)
  • 대부분의 이벤트 핸들링은 버블링 단계에서 처리됩니다.
  • 이벤트 버블링을 활용한 이벤트 위임 패턴은 효율적인 이벤트 관리를 위한 필수 기술입니다.