이벤트 위임 (Envet delegation)

96Smilepeace·2023년 4월 18일
0

기술면접

목록 보기
3/3
post-thumbnail

이벤트 위임이란?

이벤트 위임은 실제 바닐라 JS로 웹 앱을 구현할 때 자주 사용하는 코딩 패턴입니다.
하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트를 제어하는 방식입니다.

위와 같은 동작이 가능한 이유는 하위요소에서 이벤트가 발생시 버블링으로 상위요소에서도 해당 이벤트를 알 수 있기때문에 이벤트가 일어난 해당 요소만 event.target을 사용하여 하위요소의 이벤트를 컨트롤 할 수 있습니다.


이벤트 위임의 동작 알고리즘 입니다.

  1. 컨테이너에 하나의 핸들러를 할당합니다.
  2. 핸들러의 event.target을 사용하여 이벤트가 발생한 요소가 어디인지 알아냅니다.
  3. 원하는 요소에서 이벤트가 발생했다고 확인되면 이벤트를 핸들링합니다.

이벤트 위임의 장점과 단점

장점

  1. 많은 핸들러를 할당하지 않아도 되기 때문에 초기화가 단순해지며 메모리가 절약됩니다.
  2. 요소를 추가하거나 제거할 때 해당 요소에 핼당된 핸들러를 추가하거나 제거할 필요가 없기 때문에 코드가 짧아집니다.
  3. innerHTML 이나 유사한 기능을 하는 스크립트로 요소 덩어리를 더하거나 뺄 수 있기 때문에 DOM 수정이 쉬워집니다.

단점

  1. 이벤트 위임을 사용하려면 이벤트가 반드시 버블링 되어야 합니다. 하지만 몇몇 이벤트는 버블링 되지 않기에 주의가 필요합니다.
  2. 낮은 레벨에 할당한 핸들러엔 event.stopPropagation()를 사용할 수 없습니다.
  3. 컨테이너 수준에 할당된 핸들러가 응답할 필요가 있는 이벤트이든 아니든 상관없이 모든 하위 컨테이너에서 발생하는 이벤트에 응답해야 하므로 CPU 작업 부하가 늘어날 수 있습니다. 하지만 이런 부하는 무시할만한 수준이므로 실제로는 잘 고려하지않습니다.

예제

  <body>
    <div style="margin: 50px" class="container">
      <strong>To do list</strong>
      <ul class="toDoList">
        <li>
          <input type="checkbox" id="input1" />
          <label for="input1">이벤트 위임 공부하기</label>
        </li>
        <li>
          <input type="checkbox" id="input2" />
          <label for="input2">버블링 공부하기</label>
        </li>
      </ul>
    </div>
    <script>
      let inputs = document.querySelectorAll("input");
      inputs.forEach((input) => {
        input.addEventListener("click", (e) => {
          alert("click");
        });
      });
    </script>
  </body>

queryselectorAll()를 사용하여 모든 input element를 가져온 다음 각 input element에 클릭 이벤트 리스너를 추가합니다. 체크박스를 클릭하면 위와 같이 이벤트가 발생합니다.

해당 코드만 사용한다면 문제가 없겠지만 추가적으로 리스트 아이템을 추가한다면 어떻게 되는지 보겠습니다.

    <script>
      let inputs = document.querySelectorAll("input");
      inputs.forEach((input) => {
        input.addEventListener("click", (e) => {
          alert("click");
        });
      });

//추가 코드
      var itemList = document.querySelector(".toDoList");

      var li = document.createElement("li");
      var input = document.createElement("input");
      var label = document.createElement("label");
      var labelText = document.createTextNode("추가된 input");

      label.setAttribute("style", "color:red");
      input.setAttribute("type", "checkbox");
      input.setAttribute("id", "input3");
      label.setAttribute("for", "input3");
      label.appendChild(labelText);
      li.appendChild(input);
      li.appendChild(label);
      itemList.appendChild(li);
    </script>

이와 같이 적용되지 않는걸 확인 할 수 있습니다. 이벤트 등록 지점이 요소 생성 시점보다 먼저 일어났기떄문입니다, 수동적으로 요소 생성 코드를 이벤트 등록 지점 위에 작성도 가능하겠지만 코드가 지저분해질수 있으며 해당 코드에서 다시 추가로 생성된 요소에 이벤트를 등록하게되는 작업은 번거로운 작업입니다.

그렇기에 이벤트 위임을 사용하여 상위요소에서 하위요소 이벤트 처리를 해보겠습니다.

    <script>
      let container = document.querySelector(".container");
      container.addEventListener("click", (e) => {
        alert("click");
      });
    </script>

상위요소인 div에 이벤트 위임하였습니다.

동일하게 작동하는것을 볼 수 있습니다.
한가지 유의할 점은 하위 모든 요소에 적용되어strong등.. 불필요한 태그에도 적용된다는 점인데요.

event.target를 사용하여 이벤트를 제어할 수 있습니다.
최종적으로 불필요한 태그에 적용시키지 않으면서 추가로 생성된 요소에도 적용되는지 확인해보겠습니다.

    <script>
      let container = document.querySelector(".container");
      container.addEventListener("click", (event) => {
        let target = event.target;

        if (target.tagName === "INPUT") alert("click");
      });

      var itemList = document.querySelector(".toDoList");

      var li = document.createElement("li");
      var input = document.createElement("input");
      var label = document.createElement("label");
      var labelText = document.createTextNode("추가된 input");

      label.setAttribute("style", "color:red");
      input.setAttribute("type", "checkbox");
      input.setAttribute("id", "input3");
      label.setAttribute("for", "input3");
      label.appendChild(labelText);
      li.appendChild(input);
      li.appendChild(label);
      itemList.appendChild(li);
    </script>

잘 작동하는걸 확인할 수 있습니다.



이벤트 위임 기능 참고 - CAPTAIN PANGYO
이벤트 위임 기능 참고 - JAVASCRIPT.INFO

profile
🔥 노력천재

0개의 댓글