[JS] 브라우저는 어떻게 이벤트를 감지할까 - bubbling/capture/delegation

이정민 Lee Jeong Min·2021년 2월 21일
2

Javascript

목록 보기
3/10
post-thumbnail

자바스크립트에서의 이벤트 객체는 돔 내부에 위치하며 사용자가 현재 취한 액션에 대한 상세정보를 담고 있습니다.

사용자의 입력을 받기 위해 이벤트 등록을 하면, 이후 이벤트가 발생했을 때 브라우저가 이를 감지하게 됩니다.

브라우저가 이러한 이벤트를 감지하는 방식에는 두 가지가 있습니다. 바로 버블링캡쳐입니다.
돔은 트리구조를 갖는데, 트리의 노드를 타고 이벤트가 전파되게 됩니다.

Event Bubbling

이벤트 버블링은 특정 화면 요소에서 이벤트가 발생했을 때, 해당 이벤트가 더 상위의 화면 요소들로 전달되는 현상입니다.

브라우저는 특정 화면 요소에서 이벤트가 발생했을 때, 해당 이벤트를 최상위의 화면 요소까지 전파시키게 됩니다.

Event Capture

특정 이벤트가 전달되서 최상위 요소에서 감지되면, 다시 이벤트가 발생한 태그를 찾아 내려가게 됩니다. 이러한 현상이 바로 이벤트 캡쳐입니다.

이벤트리스너 api에서 옵션 객체의 capture 속성으로 탐색 방식을 바꿔줄 수 있습니다.

Event Delegation

이벤트 위임은 바닐라 자바스크립트에서 많이 사용되곤 하는 코딩 패턴입니다.
하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어할 수 있도록 하는 방법입니다.

여러 개의 인풋 박스가 있는 리스트를 예시로 들어보겠습니다.

<ul class="itemList">
	<li>
		<input type="checkbox" id="item1">
		<label for="item1">first item</label>
	</li>
	<li>
		<input type="checkbox" id="item2">
		<label for="item2">second item</label>
	</li>
</ul>

리스트 내부의 인풋 박스에 일일히 이벤트 리스너를 추가하려면 아래와 같이 작성할 수 있습니다.

var inputs = document.querySelectorAll('input');
inputs.forEach(function(input) {
	input.addEventListener('click', function(event) {
		alert('clicked');
	});
});
var itemList = document.querySelector('.itemList');

하지만 이 경우, 이벤트 위의 코드가 작성된 이후에 리스트 내부에 인풋 박스가 추가적으로 생성된다면, 해당 인풋 박스에 대한 이벤트는 감지를 하지 못하게 됩니다.


반면에 ul 태그에 이벤트 리스너를 달아서 버블링을 이용한다면, 이벤트리스너의 등록 시점과 상관없이 하위 요소들의 이벤트가 정상적으로 동작하게 됩니다.

var itemList = document.querySelector('.itemList');
itemList.addEventListener('click', function(event) {
	alert('clicked');
});

따라서 새로운 인풋 요소를 아래와 같이 추가한다면,

var li = document.createElement('li');
var input = document.createElement('input');
var label = document.createElement('label');
var labelText = document.createTextNode('third item');

input.setAttribute('type', 'checkbox');
input.setAttribute('id', 'item3');
label.setAttribute('for', 'item3');
label.appendChild(labelText);
li.appendChild(input);
li.appendChild(label);
itemList.appendChild(li);

첫 번째 방법의 경우에는 third item에 대한 클릭 이벤트가 작동하지 않는 반면,
두 번째 방법의 경우에는 잘 동작하는 것을 볼 수 있습니다.

Reference

profile
https://jeong-min.com/ <- 블로그 이전했습니다 :)

0개의 댓글