개발일지
3월 기술면접대비 - Event bubbling 과 capturing 본문
버블링 ( bubbling )
한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고, 이어서 부모 요소의 핸들러가 동작합니다. 가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작합니다.
한 요소에 이벤트가 발생하면 그 부모 요소의 이벤트도 같이 발생되는 이벤트 전파입니다.
<div onclick="alert('div에 할당한 핸들러!')">
<em><code>EM</code>을 클릭했는데도 <code>DIV</code>에 할당한 핸들러가 동작합니다.</em>
</div>
여기서 핸들러는 <div>에 할당되어 있지만 <em>이나 <code>같은 중첩 태그를 클릭해도 동작합니다.

이벤트가 제일 깊은 곳에 있는 요소에서 시작해 부모 요소를 거슬러 올라가며 발생하는 모양이 마치 물속 거품(bubble)과 닮았기 때문에 이런 흐름을 '이벤트 버블링' 이라고 부릅니다.
"거의" 모든 이벤트는 버블링 됩니다.
! focus 이벤트와 같이 버블링 되지 않는 이벤트도 있습니다.
이벤트를 처리하고 난 후 버블링을 중단하도록 명령하는 것도 가능합니다.
이벤트 객체의 메서드인 event.stopPropagation()를 사용하면 됩니다.
아래 코드에서 <button>을 클릭해도 body.onclick은 동작하지 않습니다.
<body onclick="alert(`버블링은 여기까지 도달하지 못합니다.`)">
<button onclick="event.stopPropagation()">클릭해 주세요.</button>
</body>
한 요소의 특정 이벤트를 처리하는 핸들러가 여러개인 상황에서, 핸들러 중 하나가 버블링을 멈추더라도 나머지 핸들러는 여전히 동작합니다.
event.stopPropagation()은 위쪽으로 일어나는 버블링은 막아주지만, 다른 핸들러들이 동작하는 건 막지 못합니다.
버블링을 멈추고, 요소에 할당된 다른 핸들러의 동작도 막으려면 event.stopImmediatePropagation()을 사용해야 합니다. 이 메서드를 사용하면 요소에 할당된 특정 이벤트를 처리하는 핸들러 모두가 동작하지 않습니다.
! 꼭 필요한 경우가 아니라면 버블링을 막지 마세요
추후에 문제가 될 수 있는 상황이 생길 수 있습니다.
캡처링( capturing )
표준 DOM 이벤트에서 정의한 이벤트 흐름엔 3가지 단계가 있습니다.
- 캡처링 단계 – 이벤트가 하위 요소로 전파되는 단계
- 타깃 단계 – 이벤트가 실제 타깃 요소에 전달되는 단계
- 버블링 단계 – 이벤트가 상위 요소로 전파되는 단계

만약 테이블 안의 <td>를 클릭하면 어떻게 이벤트가 흐르는지에 대한 그림입니다.
<td>를 클릭하면 이벤트가 최상위 조상에서 시작해 아래로 전파되고(캡처링 단계), 이벤트가 타깃 요소에 도착해 실행된 후(타깃 단계), 다시 위로 전파됩니다(버블링 단계). 이런 과정을 통해 요소에 할당된 이벤트 핸들러가 호출됩니다.
요약
이벤트가 발생하면 이벤트가 발생한 가장 안쪽 요소가 '타깃 요소(event.target)'가 됩니다.
- 이벤트는 document에서 시작해 DOM 트리를 따라 event.target까지 내려갑니다. 이벤트는 트리를 따라 내려가면서 addEventListener(..., true)로 할당한 핸들러를 동작시킵니다. addEventListener(..., true)의 true는 {capture: true}의 축약형입니다.
- 이후 타깃 요소에 설정된 핸들러가 호출됩니다.
- 이후엔 이벤트가 event.target부터 시작해서 다시 최상위 노드까지 전달되면서 각 요소에 on로 할당한 핸들러와 addEventListener로 할당한 핸들러를 동작시킵니다. addEventListener로 할당한 핸들러 중, 세 번째 인수가 없거나 false, {capture: false}인 핸들러만 호출됩니다.
각 핸들러는 아래와 같은 event 객체의 프로퍼티에 접근할 수 있습니다.
- event.target – 이벤트가 발생한 가장 안쪽의 요소
- event.currentTarget (=this) – 이벤트를 핸들링 하는 현재 요소 (핸들러가 실제 할당된 요소)
- event.eventPhase – 현재 이벤트 흐름 단계(캡처링=1, 타깃=2, 버블링=3)
핸들러에서 event.stopPropagation()을 사용해 이벤트 버블링을 멈출 수 있지만 추천하지 않습니다. 지금은 상위 요소에서 이벤트가 어떻게 쓰일지 확실치 않더라도, 추후에 버블링이 필요한 경우가 생기기 때문입니다.
캡처링 단계는 거의 쓰이지 않고, 주로 버블링 단계의 이벤트만 다뤄집니다. 이렇게 된 데는 논리적 배경이 있습니다.
현실에서 사고가 발생하면 지역 경찰이 먼저 사고를 조사합니다. 그 지역에 대해 가장 잘 아는 기관은 지역 경찰이기 때문입니다. 추가 조사가 필요하다면 그 이후에 상위 기관이 사건을 넘겨받습니다.
이벤트 핸들러도 이와 같은 논리로 만들어졌습니다. 특정 요소에 할당된 핸들러는 그 요소에 대한 자세한 사항과 무슨 일을 해야 할지 가장 잘 알고 있습니다. <td>에 할당된 핸들러는 <td>에 대한 모든 것을 알고 있기 때문에 <td>를 다루는데 가장 적합합니다. 따라서 <td>를 다룰 기회를 이 요소에 할당된 핸들러에게 가장 먼저 주는 것입니다.
버블링과 캡처링은 '이벤트 위임(event delegation)'의 토대가 됩니다. 이벤트 위임은 강력한 이벤트 핸들링 패턴입니다. 이에 대해서는 나중에 블로그에 다루도록 하겠습니다.
reference.
모던 JavaScript 튜토리얼.JAVASCRIPT.INFO>브라우저:문서,이벤트,인터페이스>이벤트 기초.버블링과 캡처링(22.11).https://ko.javascript.info/bubbling-and-capturing
'frontEnd > 기술면접' 카테고리의 다른 글
| 3월 기술면접대비 - JS와 비교 시 리액트를 사용하려는 이유 (0) | 2024.03.09 |
|---|---|
| 3월 기술면접대비 - React 클래스형과 함수형의 차이 (0) | 2024.03.08 |
| 3월 기술면접대비 - React의 LifeCycle ( LifeCycle Method ) (0) | 2024.03.08 |
| 3월 기술면접대비 - 데이터 10,000개를 가지고 무한 스크롤 구현시에 가장 중요하게 고려해야 할 점은? (0) | 2024.03.08 |
| 3월 기술면접대비 - "==" 과 "===" 연산자의 차이 (0) | 2024.03.07 |