자바스크립트의 addEventListener 메서드를 사용할 때 주의할 점이 한 가지 있다.
바로 이벤트 핸들러의 ‘누적 등록’이라는 것이다.

addEventListener는 동일한 HTML 요소에서 발생한 동일한 이벤트에 대해
하나 이상의 이벤트 핸들러를 누적하여 등록할 수 있다.
예컨대 다음의 코드처럼 말이다.

실습 1

<!DOCTYPE html>
<html lang="ko">
  <head></head>
  <body>
    <script>
      const $body = document.querySelector('body');

      $body.addEventListener('click', () => {
        console.log('이벤트1');
      });
      $body.addEventListener('click', () => {
        console.log('이벤트2');
      });
      $body.addEventListener('click', () => {
        console.log('이벤트3');
      });

      $body.dispatchEvent(new Event('click'));
    </script>
  </body>
</html>

결과는 아래와 같다.

콘솔 결과 이미지

실습 2

그런데 다음의 경우라면 어떻게 될까?
콜백함수가 이벤트 핸들러로 누적 등록될까 그렇지 않을까?
한 번 생각해보자.

<!DOCTYPE html>
<html lang="ko">
  <head></head>
  <body>
    <script>
      const $body = document.querySelector('body');

      $body.addEventListener('click', () => {
        console.log('이벤트1');
      });
      $body.addEventListener('click', () => {
        console.log('이벤트1');
      });
      $body.addEventListener('click', () => {
        console.log('이벤트1');
      });

      $body.dispatchEvent(new Event('click'));
    </script>
  </body>
</html>

정답은 “누적하여 등록된다”이다. 결과는 아래와 같다.

콘솔 결과 이미지

왜 이런 현상이 발생할까? 그것은 각각의 addEventListener에 전달된 콜백 함수인
() => { console.log('이벤트1'); }의 참조값이 다르기 때문이다.

다시 말해, 각각의 콜백 함수는 내용은 같으나 서로 다른 함수(객체)다.
그렇기 때문에 각각의 콜백 함수가 이벤트 핸들러로 누적 등록된다.

실습 3

반면에, 참조값이 동일한 콜백함수를 전달하면 하나의 이벤트 핸들러만 등록된다.
아래의 코드처럼 말이다.

<!DOCTYPE html>
<html lang="ko">
  <head></head>
  <body>
    <script>
      const $body = document.querySelector('body');

      const callBackFunc = () => {
        console.log('이벤트1');
      };

      $body.addEventListener('click', callBackFunc);
      $body.addEventListener('click', callBackFunc);
      $body.addEventListener('click', callBackFunc);

      $body.dispatchEvent(new Event('click'));
    </script>
  </body>
</html>

콘솔 결과 이미지

콜백함수의 참조값을 callBackFunc라는 변수에 할당한 뒤 사용하였다.
따라서, 각각의 addEventListener에 전달된 콜백함수는 당연히 같은 함수(객체)다.
그러므로 하나의 이벤트 핸들러만이 등록된다.

addEventListener 메서드를 사용할 때는 이상과 같은 ‘누적 등록’ 문제에 주의할 필요가 있다.

참고자료

“모던 자바스크립트 Deep Dive”, 이웅모, 위키북스, 2020.09.25, pp.764-765