이벤트 버블링(Event Bubbling)이란?
이벤트 버블링은 한 요소가 다른 요소 내부에 중첩되어 있고, 두 요소 모두 동일한 이벤트(예: 클릭)에 대한 리스너를 등록했을 때 이벤트 핸들러가 호출되는 순서를 의미합니다. 버블링 방식에서는 이벤트가 가장 안쪽(자식) 요소에서 먼저 감지되어 처리된 후, 바깥쪽(부모) 요소로 거품이 올라오듯 전파됩니다.
이벤트 캡처링(Event Capturing)이란?
반대로 캡처링 방식에서는 이벤트가 가장 바깥쪽(부모) 요소에서 먼저 감지되어, 안쪽(자식) 요소로 순차적으로 전파됩니다.
그럼 두 방식의 차이를 실제 예제를 통해 살펴보겠습니다.
예제용 HTML 구조
아래 두 예제 모두 다음과 같은 HTML 구조를 사용합니다.
<div id='outer' style='background-color:red;display:inline-block;padding:50px;'>
Outer Div
<div id='inner' style='background-color:yellow;display:inline-block;padding:50px;'>
Inner Div
</div>
</div>
1. 이벤트 버블링 예제
addEventListener의 세 번째 인자를 false(기본값)로 설정하면 버블링 단계에서 이벤트가 처리됩니다.
document.querySelector('#outer').addEventListener('click', e => {
console.log('Outer div is clicked');
}, false);
document.querySelector('#inner').addEventListener('click', e => {
console.log('Inner div is clicked');
}, false);위 코드를 실행한 뒤 노란색 안쪽 div를 클릭하면 콘솔에 다음과 같은 로그가 출력됩니다.
Inner div is clicked
Outer div is clicked
안쪽 요소의 핸들러가 먼저 실행되고, 그다음 바깥쪽 요소의 핸들러가 실행되는 것을 확인할 수 있습니다. 이것이 바로 버블링입니다.
2. 이벤트 캡처링 예제
이번에는 세 번째 인자를 true로 설정하여 캡처링 단계에서 이벤트가 처리되도록 해보겠습니다.
document.querySelector('#outer').addEventListener('click', e => {
console.log('Outer div is clicked');
}, true);
document.querySelector('#inner').addEventListener('click', e => {
console.log('Inner div is clicked');
}, true);동일하게 안쪽 div를 클릭하면 이번에는 실행 순서가 반대로 나타납니다.
Outer div is clicked
Inner div is clicked
바깥쪽 요소의 핸들러가 먼저 실행된 후 안쪽 요소의 핸들러가 실행됩니다. 이것이 캡처링 단계의 동작 방식입니다.
참고: 이벤트 전파 제어하기
실무에서는 특정 상황에서 이벤트 전파를 멈춰야 할 때가 있습니다. 이때는 이벤트 객체의 stopPropagation() 메서드를 사용하면 됩니다.
document.querySelector('#inner').addEventListener('click', e => {
e.stopPropagation(); // 부모 요소로의 전파를 차단
console.log('Inner div is clicked');
});또한 DOM에서 이벤트는 실제로 캡처링 → 타깃 → 버블링의 3단계로 전파됩니다. addEventListener의 세 번째 인자(useCapture)는 이 중 어느 단계에서 핸들러를 실행할지 결정하는 옵션이며, 기본값은 false(버블링)입니다.