가끔씩 프론트엔드 면접에서 이벤트 버블링, 캡쳐링에 대해 물어보시는 분이 있어 용어 정리해보고자 합니다.
이벤트 버블링과 캡처링은 HTML DOM API에서 이벤트 전파 방식으로,
다른 요소 내부의 요소에서 이벤트가 발생하고 두 요소 모두 해당 이벤트에 대한 핸들을 등록한 경우,
이벤트를 수신하는 순서에 대한 특성입니다.
event bubbling 이란 (이벤트 버블링이란)
이벤트는 먼저 가장 안쪽 요소에 의해 이벤트 핸들러가 처리된 후 외부 요소로 이벤트를 전파시켜
외부 요소의 이벤트 핸들러를 실행 시키는 것입니다.
예시를 들어 설명해보겠습니다.
아래와 같은 코드가 있다고 봅시다.
가장 안쪽의 id3 객체를 클릭하면 alert창으로 3만뜨는게 아니라,
2, 1도 뜨게 됩니다.
<div data-onclick="alert(1)" id="id1">
111
<div data-onclick="alert(2)" id="id2">
222
<div data-onclick="alert(3)" id="id3">
333
</div>
</div>
</div>
id3에 등록된 이벤트 핸들러 alert(3)이 실행이 되고나면,
그 바깥에 할당된 HTML 객체의 이벤트 핸들러인 alert(2)가 실행이 되고,
그 후에 alert(1)이 실행이 되는 식입니다.
이런 흐름을 이벤트 버블링 (event bubbling)이라고 합니다.
이벤트가 제일 깊은 곳에 잇는 요소에서 시작해 부모 요소를 거슬러 올라가며 발생하는 모습이
거품과 닮아서 이런 용어가 지어졌다고 합니다.
event capturing이란 (이벤트 캡처링이란), event trickling이란 (이벤트 트리클링이란)
이벤트는 바깥쪽 요소에 의해 이벤트 핸들러가 처리된 후 내부 요소로 이벤트를 전파시켜
내부 요소의 이벤트 핸들러를 실행 시키는 것입니다.
이벤트 버블링의 반대라고 생각하면 쉽습니다.
eventListener에 아래와 같이 세번째 인자에 true를 지정해주면 이벤트 버블링이 아닌 캡처링이 동작하게 됩니다.
즉, id3을 클릭하면 1->2->3 순서로 alert창이 뜨도록 실행이 됩니다.
var id1 = document.getElemntById('id1')
i1.addEventListener('click', ()=>{ alert(1); }, true);
var id2 = document.getElemntById('id1')
i1.addEventListener('click', ()=>{ alert(2); }, true);
var id3 = document.getElemntById('id1')
i1.addEventListener('click', ()=>{ alert(3); }, true);
event trickling(이벤트 트리클링)은 event bubbling과 동일한 뜻입니다.
주의해야할 점중에 하나로는, IE9버전 이하에서는 이벤트 캡처링을 지원하지는 않습니다.
문제 - 이벤트 캡처링과 버블링이 동시에 있을 경우
한 엘리먼트에 캡처링과 버블링이 동시에 등록될경우, 어떻게 동작할까요?
아래 예제를 살펴보고 div2와 div4를 눌렀을때 각각 어떻게 표시되는지 확인해봅시다.
<script>
function addClickListener (msg, num, type) {
document.querySelector("#div" + num).addEventListener("click", () => alert(msg + num), type);
}
bubble = (num) => addClickListener("bubble ", num, false);
capture = (num) => addClickListener("capture ", num, true);
// 캡처링 등록후 버블링 등록
capture(1);
capture(2);
bubble(2);
bubble(1);
// 버블링 등록후 캡처링 등록
bubble(3);
bubble(4);
capture(4);
capture(3);
</script>
<style>
#div1, #div2, #div3, #div4 {
border: solid 1px;
padding: 3px;
margin: 3px;
}
<style>
<html>
<div id="div1">
div 1
<div id="div2">
div 2
</div>
</div>
<div id="div3">
div 3
<div id="div4">
div 4
</div>
</div>
</html>
힌트로는 eventListner 등록을 먼저 한 콜백함수가 먼저 실행이 됩니다.
힌트까지 드렸지만 정답은 알수없다 혹은 브라우저마다 다르다입니다.
브라우저마다 다른것으로 확인되는데요, vivaldi와 chrome 에서 각각 실행하였을때,
아래와 같이 실행이 됩니다.
vivaldi
div2를 눌렀을 때 : capture1 > capture2 > bubble2 > bubble1
div4를 눌렀을 때 : capture3 > bubble4 > capture4 > bubble3
chrome
div2를 눌렀을 때 : capture1 > capture2 > bubble2 > bubble1
div4를 눌렀을 때 : capture3 > capture4 > bubble4 > bubble3
따라서 버블링과 캡쳐링 둘중에 하나만 사용하시길 바랍니다.
총평
캡쳐링이라는 용어는 왜 캡쳐링인지 잘 모르겠습니다.
보통 따로 신경쓰지 않으면 버블링을 자연스럽게 쓰게 되고,
또 겹쳐져 있는 UI에 event를 등록하는 경우가 잘 없다보니 생소한 개념이었습니다.
개발하면서 이 용어를 사용하거나 캡쳐링 옵션을 사용한 적은 따로 없었습니다.
개인적으로는 이벤트핸들러가 겹칠만한 UI를 만드는것은 안 좋은 UI라고 생각하는데,
캡쳐링/버블링을 신경써서 개발해야한다면 UI를 바꿔야하는것은 아닌가 생각이 들기도 합니다.
면접 개발자 질문중에 이따금씩 나오는 질문이라서 다뤄보았는데, 면접질문으로 적절한 질문인지는 잘 모르겠습니다.
event 전파에 관해서는 event전파를 막는 방법도 javascript에서 제공하고 있는데, 기회가 된다면 이 주제에 대해서도 다뤄보겠습니다.
javascript - event bubbling이란, event capturing이란, event trickling이란 (이벤트 버블링이란, 이벤트 캡처링이란, 이벤트 트리클링이란)
#event,#capture,#bubble,#capturing,#bubbling,#javascript,#script,#이벤트,#캡처,#캡쳐,#캡처링,#캡쳐링,#버블링,#버블,#자바스크립트
댓글