/ ETC

이벤트 버블링과 캡처링

기타 포스팅입니다.




오늘은 이벤트 버블링과 캡처링에 대해서 알아보겠습니다.
이게 도대체 무엇일까요?

버블링과 캡처링

<div onclick="alert('DIV에 할당된 클릭이벤트')">
    <p>눌러봐</p>
</div>

위의 핸들러는 <div>에 할당이 되어있습니다. 하지만 그 안에있는 <p>태그를 눌러도 핸들러가 동작합니다. 뭔가 이상하지 않나요?? 분명 <p>태그를 눌렀는데 왜 <div>에 할당된 핸들러가 동작하는걸까요…?

<form onclick="alert('form')">FORM
  <div onclick="alert('div')">DIV
    <p onclick="alert('p')">P</p>
  </div>
</form>

또 다른 예시를 보면서 알아보겠습니다.

위 HTML코드를 보면 <form>태그 안에 <div>태그가 있고, 또 그 안에는 <p>태그가 있습니다. 그리고 각 태그에는 클릭 이벤트 핸들러가 할당되어 있는 상태입니다.

가장 안쪽에 존재하는 <p>태그를 클릭하면 다음 순서대로 동작합니다.

  1. 먼저 <p>의 핸들러가 동작합니다.
  2. 그 다음 상위태그인 <div>의 핸들러가 동작합니다.
  3. 그 다음 상위태그인 <form> 핸들러가 동작합니다.
  4. document 객체를 만날 때까지, 각 요소에 할당된 onclick 핸들러가 동작합니다.



다음과 같은 과정으로 alert창이 p -> div -> form 순으로 3개가 열립니다. 이러한 흐름을 ‘이벤트 버블링’이라고 하는 것입니다. 가장 안쪽의 요소부터 가장 최상단까지 거슬로 올라가면서 발생하는 모양이 물속의 거품(bubble)과 닮았기 때문이라고 합니다.

‘버블링’과 반대로, 상위요소에서 하위요소로 이벤트가 전파되는 경우를 ‘이벤트 캡처링’이라고 합니다. 물론 자주쓰이는 경우는 아닙니다.

Event Flow

DOM 이벤트는 3가지 단계가 존재합니다.

  1. Capture Phase (캡처링 단계)
  2. Target Phase (타켓 단계)
  3. Bubble Phase (버블링 단계)

    기본적으로 이벤트 흐름은 Capture Phase 👉🏼 Target Phase 👉🏼 Bubble Phase 순으로 흐르게 됩니다. 그런데 여기서 의문이 생깁니다.

이벤트 플로우 설명
DIV와 BODY와 HTML 모두 클릭 이벤트가 있다고 가정해보겠습니다.
div를 클릭하게 되면 위의 이벤트 흐름에 따라서 다음과 같이 이벤트가 발생할 것 입니다.

  1. 캡처링 단계에 의해 HTML 클릭이벤트 => body 클릭이벤트 순으로 발생
  2. 타켓 단계에 의해 이벤트의 target인 div의 클릭이벤트 발생
  3. 버블링 단계에 의해 ody 클릭이벤트 => HTML 클릭이벤트 순으로 다시 발생


그러면… 저 DIV하나 눌렀다고 클릭이벤트가 몇번 발생하게 되는거지…?
그렇습니다. 정말 복잡해집니다.

그래서 저 DIV, 즉 이벤트를 발생시킨 주체를 제외한 나머지 요소들은 이벤트가 캡처단계에서 발생될 것인지, 버블단계에서 발생될 것인지 선택할 수 있습니다.
기본적으로 브라우저는 ‘버블’이 기본값입니다.

const html = document.documentElement;
const body = document.body;
const div = document.querySelector('div');

div.addEventListener('click', function () {
  console.log('DIV')
})
body.addEventListener('click', function () {
  console.log('BODY')
}, true)
html.addEventListener('click', function () {
  console.log('HTML')
})

위 처럼 이벤트리스너의 첫번째 인자는 이벤트 타입, 두번째 인자는 리스너가 들어가는데 세번째인자로 true, false값을 넣어줄 수 있습니다. 기본값은 false이고 아무값도 넣지 않는다면 false인 상태로 ‘버블’인 것이고, true값을 넣어준다면 ‘캡처’가 적용되는 것입니다.
위에서는 body에 true를 넣어서 캡처링을 적용한 것입니다.

이렇게 이벤트 캡처링과 버블링에 대해서 정리해보았습니다.

End.