이번 장에서는 앞에서 다뤄봤던 event.target 에 대한 추가적인 설명과 이벤트 위임에 대해 얘기해 보겠습니다. 우선 앞에서 사용했던 코드를 다시 살펴보겠습니다.

<div class="btns">
	<button type="button" class="btn">버튼1</button>
  <button type="button" class="btn2">버튼2</button>
  <button type="button" class="btn2">버튼3</button>
</div>
const btn = document.querySelector('.btns');
function clickTest(event){console.log(event.target)}
btn.addEventListener('click', clickTest);

위의 코드를 작성하고 버튼을 클릭했을 때 콘솔 창에는 클릭한 버튼들이 출력되는 걸 보실 수 있었습니다. 이상하지 않나요? 이벤트는 분명 <div class="btns"> 요소에 걸려 있음에도 불구하고 왜 버튼들 하나하나에 이벤트가 걸려 있는 것처럼 작동할까요? 이 원리를 이해하기 위해서는 먼저 이벤트의 흐름을 알아야 합니다.

이벤트의 흐름은 돔 트리의 줄기에서 가지로 가는 캡 단계(window → document → html → body → element)와 가지에서 줄기로 전파되는 버블링 단계(element → body → html → document → window)로 나눌 수 있습니다.

https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4d44cd92-3a9a-45bd-ad37-07a17f60ad43/_2019-08-08__12.33.25.png

위의 그림에서 이벤트는 (1) ~ (5)의 순서로 진행되는 것을 확인할 수 있습니다. 이런 이벤트의 흐름 때문에 <div class="btns"> 안에 포함된 <button> 을 클릭했을 때도 <div class="btns">에 연결된 click 이벤트를 호출하는 것이 가능합니다. 최초로 <button> 을 클릭했을 때, 그 이벤트가 버블링을 통해 반드시 그 부모인 <div class="btns">를 거쳐갈 것이기 때문입니다. 그리고 이때 이벤트 리스너의 함수에 전달되는 event 개체는 이벤트가 최초에 발생된 개체에 대한 참조를 제공합니다. 그 참조가 바로 event.target 메서드의 반환 값이며 이벤트의 진원지라고 할 수 있습니다. 이제 이해가 가시나요? 이렇게 참조를 통해 이벤트를 발생시키는 것을 이벤트 위임이라고 합니다. 덕분에 우리는 아래 코드처럼 굳이 각각의 버튼에 이벤트 리스너를 달지 않고도 마치 이벤트 리스너가 달려 있는 것처럼 사용할 수 있습니다. 이것이 바로 이벤트 위임 입니다.

const btn = document.querySelector('.btns');
const btn1 = document.querySelector('.btn');
const btn2 = document.querySelector('.btn2');
const btn3 = document.querySelector('.btn3');
function clickTest(event){console.log(event.target)}
btn1.addEventListener('click', clickTest);
btn2.addEventListener('click', clickTest);
btn3.addEventListener('click', clickTest); /*이렇게 각각 버튼마다 이벤트를 주는건 피곤하죠!*/