[JavaScript] 이벤트 위임(Event Delegation)

roadzmoon76·2022년 5월 14일
0

To the JavaScript Master

목록 보기
1/1
post-thumbnail

🏫 비유 : 당신은 교장입니다.

당신은 자바스크립트 고등학교의 교장 선생님이다. 오늘 결석한 학생들을 알고 싶은데 다음 두 가지 방법이 있다면 어떤걸 선택하겠는가?

  1. "출석부" 를 들고 직접 각 교실들을 다니며 결석한 학생들을 체크한다.
  2. 교감 선생님에게 "출석부" 를 주며 오늘 결석한 학생들을 체크해오라 한다.(그럼 교감 선생님은 담임 선생님에게... 담임 선생님은 반장에게...)

당신이 산책을 좋아하거나 여유가 넘치는게 아니라면 2번을 선택하는게 효율적일 것이다.

자바스크립트에서도 효율적인 이벤트 처리를 위해 2번과 비슷한 방식을 채택하고 있는데, 그게 바로 이벤트 위임(Event Delegation) 이다.


📖 사전학습 : 이벤트 전파(Event Propagation)란?

이벤트 위임을 알기 위해선 먼저 자바스크립트에서 이벤트 전파의 동작 방식을 알아야 한다.

앞선 비유에서 "결석" 이라는 이벤트가 "출석부" 를 매개로 고등학교 위계질서를 통해 전달되듯이, DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전달되는데 이를 이벤트 전파(Event Propagation) 라고 한다. 아래 예제를 보자.

<ul id="cars">
  <li id="benz">Benz</li>
  <li id="bmw">Bmw</li>
  <li id="audi">Audi</li>
<ul>
document.querySelector('#bmw').addEventListener('click', () => console.log("우왕 BMW!"));

id 가 bmw 인 li 요소를 클릭하면 클릭 이벤트가 발생한다. 이때 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소의 이벤트 타깃(event target)을 중심으로 DOM 트리를 통해 전파된다. 이벤트 전파는 이벤트 객체가 전파되는 방향에 따라 아래 그림과 같은 3단계로 구분할 수 있다.

  • 캡처링 단계(capturing phase) : 이벤트가 상위 요소에서 하위 요소 쪽으로 전파
  • 타깃 단계(target phase) : 이벤트가 이벤트 타깃에 도달
  • 버블링 단계(bubbling phase) : 이벤트가 하위 요소에서 상위 요소 쪽으로 전파

즉 자바스크립트는 이벤트가 발생하여 생긴 이벤트 객체가 window 에서 시작해서 타깃에 도달했다가 다시 window 로 가게 된다. 다만 기본적인 이벤트 등록 방식들로는 타깃 단계와 버블링 단계만 캐치할 수 있고, addEventListenr() 메서드 방식으로 등록후 3번째 인수로 true 를 전달할 경우에만 캡처링 단계의 이벤트를 캐치할 수 있다. 아래 예시에서 종합하여 살펴보자.

<ul id="cars">
  <li id="benz">Benz</li>
  <li id="bmw">Bmw</li>
  <li id="audi">Audi</li>
<ul>
const $cars = document.querySelector('#cars');
const $bmw = document.querySelector('#bmw');

$cars.addEventListener('click', () => {
  console.log("캡처링 단계");
}, true);

$bmw.addEventListener('click', () => {
  console.log("타깃 단계");
});

$cars.addEventListener('click', () => {
  console.log("버블링 단계");
});

위 예제에서 두번째 li 인 bmw 태그를 클릭하면 콘솔에 아래와 같이 찍힌다.

캡처링 단계
타깃 단계
버블링 단계

이처럼 이벤트는 이벤트를 발생시킨 이벤트 타깃 뿐만 아니라 상위 DOM 요소에서도 캐치할 수 있다.


🔥 본론 : 이벤트 위임(Event Delegation)이란?

이벤트 위임(Event Delegation)이란 위와 같은 자바스크립트의 이벤트 전파 특성을 이용해서 여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법을 말한다. 이벤트 위임으로 인해 얻는 이점들은 다음과 같다.

  • 여러 개의 하위 DOM 요소에 일일이 이벤트 핸들러를 등록할 필요가 없이 상위 DOM 요소에만 등록하면 되므로 코드가 깔끔해지고 성능상의 이점이 있다.
  • 동적으로 하위 DOM 요소를 추가하더라도 일일이 추가된 DOM 요소에 이벤트 핸들러를 등록할 필요가 없다.

단, 이벤트 위임을 사용하면 상위요소에 이벤트 핸들러를 등록하기 때문에 이벤트를 실제로 발생시킨 DOM 요소가 개발자가 기대한 하위 DOM 요소가 아닐 수도 있다. 그러므로 이벤트에 반응이 필요한 DOM 요소만 이벤트 핸들러가 실행되도록 이벤트 타깃을 검사할 필요가 있다. 아래 예시를 보자.

<ul id="cars">
  <li id="benz">Benz</li>
  <li id="bmw">Bmw</li>
  <li id="audi">Audi</li>
  <div>Hyundai</div>
<ul>
const $cars = document.querySelector('#cars');

$cars.addEventListener('click', (e) => {
  console.log(e.target.innerText);
});

개발자는 Benz, Bmw, Audi 의 반응만 보고싶었으나 의도치않게 Hyundai 도 반응을 하게됐다. 인수로 전달된 선택자에 의해 특정 노드가 선택된건지 확인해주는 Element.matches() 메서드를 이용하여 원래의 의도대로 실행되도록 수정해보자.

const $cars = document.querySelector('#cars');

$cars.addEventListener('click', (e) => {
  if (!e.target.matches('#cars > li')) return;

  console.log(e.target.innerText);
});

이제 원래 의도대로 작동하게됐다! 😎


📚 참고자료

profile
크론병걸린 자퇴생, 개발자되기

0개의 댓글