항상 실무형 개발자라고 내 자신을 소개해 왔었다.
하지만 최근 면접을 보면서 내가 실제로 경험했고, 해결한 문제라고 하더라도 해당 문제가 어떤 이론적 배경을 가지고 있는지 설명을 제대로 할 수 없었다. 잘 모르니까 그런 것이다. 이 버블링 역시 마찬가지다.(캡쳐링은 처음 들었지만)
https://ko.javascript.info/event-delegation
모던 Javascript 튜토리얼이라는 ebook 번역 사이트에서 아주 설명이 잘 되있었다.
번역해주신 여러분들께 감사 드립니다.
위 사이트에 따르면, 버블링이란
한 요소에 이벤트가 발생할 시, 요소의 핸들러가 동작하고 부모 요소의 핸들러가 함께 동작하는 것. 그 부모의 부모에도 핸들러가 있다면 따라 올라가면서 같이 실행된다.
몇몇 이벤트를 제외하고, 이 동작은 항상 일어난다.
또한, 해당 이벤트에 대해서 event.target, event.currentTarget 두 가지의 컨텍스트를 바라볼 수 있다.
https://codepen.io/jihyeonjeong11/pen/NWYBEGm
이해를 돕기위한 코드펜
js에서 모든 element에 이벤트를 걸어 주었다.
alert('current ' + event.target.id + ', this ' + event.currentTarget.id)
위처럼 event.target과 this를 출력하게끔 해 놓았는데, 이 경우
nested된 마지막 button을 클릭할 경우,
event.target은 inner에서 바뀌지 않음. this는 inner부터 시작해서 버블링으로 상위 이벤트가 순서대로 실행되므로 outer 3~1까지 실행될 것이다.
생각했던 대로 잘 실행이 된다.
// event.stopPropagation()
그리고 해당 메소드를 호출해 위 버블링을 막을 수 있다.
다만 이런 액션은 권장하지 않는데,
버블링을 막아버릴 경우, 유저 행동 데이터를 수집하기 위해 요소마다 click 이벤트를 달아 놓고 stopPropagation해버릴 경우, 요소별로 클릭되었다는 것을 수집하기 위한 버블링이 막혀버리기 때문이다.
이 부분은
let event = new Event(type[, options]);
와 같은 방식으로 커스텀 이벤트를 선언하며, options 인자에 bubbles : false를 넣어줌으로써 stopPropagation을 쓰지 않고 사용할 수 있다.
표준 DOM 이벤트에서 정의한 이벤트 흐름엔 3가지 단계가 있다고 한다.
캡처링 단계 – 이벤트가 하위 요소로 전파되는 단계
타깃 단계 – 이벤트가 실제 타깃 요소에 전달되는 단계
버블링 단계 – 이벤트가 상위 요소로 전파되는 단계
따라서, 사실 이벤트 실행 -> 버블링 이전에는 캡처링이라는 단계가 또 있는 것.
위의 코드펜 코드에서, 리스너 부분을 true로 바꾸어 주면 위의 이벤트리스너는 캡쳐링 과정에서만 실행된다고 한다.
그렇다면 버블링 순서와는 반대로, 맨 위 엘리먼트에서 맨 아래로 내려올 것이고,
이 경우, 맨 하단의 버튼을 클릭할 시 event.target은 inner, this는 outer1~inner로 반대로 작동할 것이다.
e.addEventListener("click", clickEvent, true)
생각했던 대로 잘 실행된다.