이벤트 전파, 구조부터 활용까지

Hushed_Mind·2025년 4월 20일

JavaScript

목록 보기
6/7
post-thumbnail

브라우저에서 버튼을 클릭하거나 키보드를 입력하면,
그 이벤트는 단지 한 요소에서만 처리되는 것이 아니다.
DOM 트리 전체를 타고 흐르며, 캡처링 → 타겟 → 버블링이라는 3단계 과정을 거친다.

이 구조를 정확히 이해하는 것은
이벤트 위임, 동적 요소 처리, stopPropagation의 쓰임새를 이해하는 데 필수적이다.


이벤트 전파란?

이벤트 전파(Event Propagation)란,
브라우저가 특정 요소에서 이벤트가 발생했을 때,
그 이벤트가 DOM 트리를 따라 상위 또는 하위 요소로 이동하면서 전파되는 흐름을 말한다.

이벤트 전파는 총 3단계로 구성된다:

  1. 캡처링(Capturing)
  2. 타겟(Target)
  3. 버블링(Bubbling)

1단계: 캡처링 (Capturing Phase)

이벤트가 DOM 최상위 요소(document)에서부터 시작해
이벤트가 실제 발생한 타겟 요소까지 내려오는 과정이다.

<body>
  <div id="outer">
    <button id="inner">Click</button>
  </div>
</body>

button을 클릭하면, 이벤트는 다음 순서로 "내려간다"

document -> html -> body -> div#outer -> button#inner

이때 각 단계에서 {capture: true} 옵션이 걸려 있는 리스너만 실행된다.

document.body.addEventListener(
	"click",
  () => console.log("캡쳐링: body"),
  {capture: true}
);

2단계: 타겟 (Target Phase)

이벤트가 실제로 발생한 요소(이벤트 타겟)에 도달한 시점이다.
즉, 사용자가 클릭한 그 요소에서 click,input,change 등 이벤트가 실제 트리거된다.
이 시점에서는 캡처링/버블링 여부와 상관없이 항상 실행된다.

document.getElementById("inner").addEventListener("click", () => {
	console.log("타깃 단계");
})

3단계: 버블링 (Bubbling Phase)

타겟 요소에서 이벤트가 끝나면,
이제는 반대로 DOM 트리를 상위 요소로 올라가면서 전파된다.

button#inner -> div#outer -> body -> html -> document
document.body.addEventListener("click", () => {
	console.log("버블링: body");
}); // capture: false 가 기본값

실습 예시: 캡처링 vs 버블링

<div id="outer">
  <button id="inner">Click me</button>
</div>
document.getElementById("outer").addEventListener(
  "click",
  () => console.log("캡처링 - outer"),
  { capture: true }
);

document.getElementById("outer").addEventListener("click", () =>
  console.log("버블링 - outer")
);

document.getElementById("inner").addEventListener("click", () =>
  console.log("타겟 - inner")
);

결과 순서

캡처링 - outer
타겟 - inner
버블링 - outer

전파를 막고 싶다면?

element.addEventListener("click", (e) => {
	e.stopPropagation();
})
  • e.stopPropagation() -> 이벤트가 이후 단계로 전달되지 않게 함
  • stopImediatePropagation() -> 현재 요소의 다른 리스너도 실행하지 않음

사용 예:

  • 모달 내부 클릭은 유지하되, 바깥 영역 클릭 시 닫기
  • 중첩된 이벤트 중 원하는 레벨까지만 실행하고 그 이상은 막기

이벤트 위임(Event Delegation)과의 연결

이벤트 전파를 이용하면, 하나의 부모 요소에 리스너를 걸고
자식 요소의 이벤트까지 처리하는 방식, 즉 이벤트 위임을 구현할 수 있다.

document.getElementById("list").addEventListener("click", (e) => {
	if (e.target.matches("li") {
    	console.log(`클릭한 항목: ${e.target.textContent}`);   
    })
})

이벤트 위임은 동적 요소 처리, 성능 최적화, 메모리 절약 등에 매우 효과적이다.


마무리

  • 브라우저는 이벤트 발생 시 DOM 트리를 따라 위에서 아래로(캡처링), 아래에서 위로(버블링) 흐름을 따라 이벤트를 전달한다.
  • addEventListener의 세 번째 인자 { capture: true }를 통해 캡처링 리스너 등록이 가능하다.
  • stopPropagation()을 통해 중간에서 이벤트 흐름을 끊을 수 있다.
  • 이 구조는 이벤트 위임(Event Delegation) 같은 패턴을 가능하게 하고, 효율적인 DOM 제어를 가능하게 한다.
profile
개발 공부 블로그

0개의 댓글