이벤트 위임이란?

이동규 (Justin)·2022년 5월 8일
1

누구에게 위임하는가?

"위임" 의 의미를 먼저 생각해보자.

인간 세상에서의 권한 위임이라 하면 보통 권한을 가진 윗사람(?)이 아랫사람(?)에게 하는 것으로 생각되지만, 우리가 알아볼 DOM 세상에서는 그 반대이다.

일반적으로 이벤트의 처리권한은 해당 이벤트가 일어난 DOM(이벤트 타겟)에 있기 때문이다.

🧳 Event Delegation은 아랫DOM(?)이 윗DOM(..)에게 이벤트를 대신 처리해달라고 위임하는 것을 의미한다.


<outer onclick={function (e) { console.log(`${e.target}이 클릭되었다!`) }}>
  윗돔
  <inner>아랫돔1</inner>
  <inner>아랫돔2</inner>
  <inner>아랫돔3</inner>
</outer>

이런 상황에서는 윗돔이 아랫돔들의 클릭 이벤트를 대신 처리해줄 수 있게 된다. 이것이 이벤트 위임이다.

왜 위임하는가?

여러모로 관리가 편해진다. 개발자들은 반복을 줄이는 쪽으로 코드를 작성하고 싶기 마련이다. 코드 상으로도 그렇지만, 이벤트 위임은 컴퓨터도 이벤트 핸들러를 반복적으로 등록하지 않아도 되도록 만들어주는 코딩 패턴이다.

위 예제를 예로 들면, 아랫돔들이 백만개로 늘어나면 이벤트 핸들러를 백만번 등록해주어야 한다.
백만개를 감싸고 있는 엘리먼트에 이벤트(처리)를 위임하면, 한개의 이벤트 핸들러로 모든 이벤트를 처리할 수 있게 된다!

🧳 이벤트를 관리하는 대형 프랜차이즈 본사(?)를 만드는 것이라고 생각하면 어떨까..

이런 것들을 위임

꼭 공통된 이벤트만을 위임하지 않아도 된다.

이벤트 위임을 조금 더 활용도 높게 사용하려면 아래와 같이 dataset 프로퍼티를 사용해 각각의 DOM에 키워드를 부여하고, 이 키워드들을 이용해 이벤트 핸들링을 casify 해줄 수 있다.


<html>
  <body>
    <div id="menu">
      <button id="save" data-action="save">저장하기</button>
      <button id="refresh" data-action="refresh">새로고침하기</button>
      <button id="play" data-action="play">재생하기</button>
    </div>

    <script>
      console.log(menu); // 따로 가져오지 않아도 element를 참조합니다.

      /* 
      	아래와 같이 클래스를 만들어주면
      	Menu와 관련된 함수들(Menu가 대리로 처리하는 여러개의 이벤트 핸들러)을
      	"하나의 관심사" 로 묶어서 표현 / 관리할 수 있습니다.
      */
      class Menu {
      	constructor(elem) {
	      this._elem = elem; // menu 인스턴스의 내부 프로퍼티(앞에 _를 붙였습니다)로 저장합니다.
		  /*
            이벤트 리스너에서 this는 이벤트 타겟을 가리킵니다.
            우리는 onClick 내부에서 this[action] 으로 인스턴스의 메서드를 참조해서 사용해야 하기 때문에,
            this를 Menu 인스턴스로 바인딩 시켜줍니다.
          */	
    	  elem.onclick = this.onClick.bind(this);
        }

        save() {
        console.log(this._elem);
        	alert("저장하기");
        }

        load() {
        	alert("저장하기");
        }

        search() {
        	alert("저장하기");
        }

        onClick(event) {
          let action = event.target.dataset.action;

          if (action) {
	          this[action]();
          }
      	}
      }

      new Menu(menu);
    </script>
  </body>
</html>

참고자료

https://ko.javascript.info/event-delegation

profile
Frontend Developer, JamStack, Ethereum

0개의 댓글