FE/기본 개념

이벤트 버블링(Event Bubbling) / 이벤트 캡처링(Event Capturing) / 이벤트 위임(Event Delegation)

yhkim_ 2025. 5. 21. 11:47

 

 

이벤트 전파 단계(Evnet Propagation Phases)

Dom에서 이벤트는 총 3단계를 거쳐서 전파된다.

1. 캡처링 단계(Caturing Phase)
2. 타겟 단계(Target Phase)
3. 버블링 단계(Bubbing Phase)

 

 

1. 캡처링 단계(Caturing Phase)

이벤트가 Window -> document -> html -> body -> 자식 요소까지 내려감

addEventListener(..., { capture: true }) 설정한 핸들러만 이 단계에서 실행됨

 

 

2. 타겟 단계(Target )

 

  • 이벤트가 실제로 발생한 요소에 도착
  • 해당 요소에 등록된 핸들러들이 실행됨
  • 이때 capture: true와 false 둘 다 실행될 수 있음 (순서: capture → bubble)

 

 

3. 버블링 단계(Bubbling)

 

  • 이벤트가 타깃 요소에서 시작해서 다시 부모 요소를 거쳐 window까지 올라감
  • 이게 우리가 주로 사용하는 기본적인 이벤트 전파 방식
  • addEventListener(..., { capture: false }) 또는 생략 시 → 이 단계에서 실행됨

 

 

 

✅ 흐름 예시

<html>
  <body>
    <div id="parent">
      <button id="child">Click me</button>
    </div>
  </body>
</html>

 

child를 클릭했을 때 이벤트 흐름을 보면 

[1] window → document → html → body → #parent → #child      (캡처링)
[2] #child                                                  (타깃 단계)
[3] #child → #parent → body → html → document → window       (버블링)

 

  • 캡처링 단계가 먼저 실행됨
  • 그다음 타깃 요소에서 이벤트 핸들러 실행
  • 그 후 버블링 단계로 전파됨

 


📌이벤트 버블링(Event Bubbling)이란?

 

 이벤트가 발생한 자식 요소에서 부모 요소로 전파되는 현상이다.

예를 들어 버튼 클릭 이벤트가 부모 div로 전파되는걸 말한다. 이걸 활용해서 이벤트 위임(Event Delegation)을 사용할 수 있고

필요하다면 stopPropagation()으로 전파를 막을 수 있다. 

 

예시

<div id="parent">
  <button id="child">클릭</button>
</div>

document.getElementById("parent").addEventListener("click", () => {
  console.log("부모 div 클릭됨");
});

document.getElementById("child").addEventListener("click", () => {
  console.log("버튼 클릭됨");
});

 

실행결과

버튼 클릭됨
부모 div 클릭됨

 

버튼(child)를 클릭했지만 parent의 이벤트도 함께 동작하는 것을 볼 수 있다. 

이처럼 이벤트는 자식에서 부모 방향으로 전파된다.

 


 

📌이벤트 캡처링(Event Capturing)이란?

이벤트 버블링과 반대 전파되는데 바깥-> 안쪽(부모->자식)으로 전파되는 현상을 말한다.

 

캡처링은 

- 이벤트가 자식까지 도달하기 전에 먼저 가로채고 싶을 때

- 예를 들어, 특정 요소가 이벤트를 무조건 막아야하는 경우

 

 

 

📌이벤트 위임(Event Delegation)이란?

이벤트 위임은 여러 자식 요소에 각각 이벤트를 거는 대신, 공통 부모 요소에만 이벤트를 등록하고

버블링을 활용해 자식의 이벤트를 처리하는 방식이다.

 

동적으로 생성된 요소에도 이벤트를 처리할 수 있어 시무에서 많이 사용된다.

 

이 이벤트 캡쳐링을 사용하는 이유는?

 

1. 성능 최적화

   - 100개의 버튼이 있다고 가정하면, 각 버튼마다 이벤트를 등록하는 건 부담스럽다

   - 이때, 이벤트를 하나만 등록하고 버블링을 이용해 어떤 버튼이 눌렸는지만 판단하면 훨씬 효율적이다.

2. 동적으로 생긴 요소에도 자동 적용

   - JS로 만든 새로운 버튼에도 자동으로 이벤트가 적용된다.

   - 자식 요소가 새로 생기고 없어져도, 부모는 그대로라서 유지보수가 쉽다.

 

 

실무에서 자주 쓰는 예시

 

  • 테이블에서 각 행 클릭
  • 리스트에서 삭제 버튼 클릭
  • 드롭다운, 모달, 메뉴 토글
  • SPA 앱에서 라우팅 처리 (예: 링크 클릭 감지)

 

 

<ul id="list">
  <li>아이템 1</li>
  <li>아이템 2</li>
</ul>
document.getElementById("list").addEventListener("click", (e) => {
  if (e.target.tagName === "LI") {
    console.log("클릭된 아이템:", e.target.textContent);
  }
});

 

 


✅ stopPropagtion()란?

이벤트가 상위요소로 전파되는 것을 막고 싶을 때 사용하는 매서드.

=> 이벤트 전파(버블링/캡처링)를 막음

 

이렇게 하면 부모 요소로 전파가 차단되어 parent의 이벤트는 발생하지 않는다.

document.getElementById("child").addEventListener("click", (e) => {
  e.stopPropagation();
  console.log("버튼 클릭됨 (전파 중단)");
});

 

 

✅ preventDefault()란?

브라우저의 기본 동작을 막음

(ex. form 제출, 링크 이동 등)

document.querySelector("a").addEventListener("click", (e) => {
  e.preventDefault(); // 링크 이동 막기
});