이벤트

2024. 4. 23. 23:03자바스크립트

이벤트와 이벤트 핸들러

브라우저는 처리해야 할 특정 사건이 발생하면 이를 감지하여 이벤트를 발생시킨다. 이벤트가 발생되었을 때 실행되는 함수를 이벤트 핸들러라 하고, 이벤트가 발생했을 때 브라우저에게 이벤트 핸들러의 호출을 위임하는 것을 이벤트 핸들러 등록이라고 한다.

이벤트가 언제 발생할 지는 예상할 수 없다. 따라서 이벤트가 발생했을 때 호출되는 함수도 개발자가 명시적으로 호출하지 않고 브라우저에게 이벤트가 발생하면 이 함수를 호출하라고 위임권을 주는 것이다.


이벤트 핸들러 등록하기

이벤트 핸들러를 등록하는 방식에는 이벤트 핸들러 어트리뷰트, 이벤트 핸들러 프로퍼티, addEventListener 메서드 방식이 있다. addEventListener 방식을 많이 사용하지만 세 방식의 차이점이 무엇이고 왜 addEventListener를 많이 사용하는지 궁금했다.

 

이벤트  핸들러 어트리뷰트

<!DOCTYPE html>
<html>
  <body>
    <button onclick="sayHi('Lee')">Click!</button>
    <script>
      function sayHi(name) {
        console.log(`Hi! ${name}`);
      }
    </script>
  </body>
</html>

리액트를 해봤다면 익숙한 모양이다.

여기서 의아한 점은 이벤트 핸들러는 콜백함수처럼 함수의 참조값을 전달해야 브라우저가 이벤트 핸들러를 호출할 수 있다는 것이다. 그런데 위의 코드에는 함수의 호출문을 이벤트 핸들러 어트리뷰트에 할당했다. 

사실 이벤트 핸들러 어트리뷰트에 할당한 함수는 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미한다.

function onclick(event) {
    sayHi('Lee');
 }

만일 함수의 참조값을 전달해야한다면 이벤트 핸들러에 인수를 전달하기 곤란하다.

<button onclick="sayHi">Click!</button>

이벤트 핸들러 어트리뷰트에 할당한 함수는 암묵적으로 생성될 이벤트 핸들러의 함수 몸체가 되므로 여러 개의 문을 할당해도 괜찮다.

<button onclick="console.log('Hi'); console.log('Lee');">Click!</button>
function onclick(event) {
    console.log('Hi');
    console.log('Lee');
 }

HTML 요소와 자바스크립트의 관심사가 다르므로 혼재하는 것보다 분리하는 것이 좋다.

하지만 리액트와 같은 경우 HTML 요소와 자바스크립트를 뷰를 구성하기 위한 구성 요소로 보기 때문에 관심사가 다르다고 생각하지 않는다. 따라서 이벤트 핸들러 어트리뷰트 방식을 사용한다.

 

이벤트 핸들러 프로퍼티 방식

<!DOCTYPE html>
<html>
  <body>
    <button>Click!</button>
    <script>
      const $button = document.querySelector('button');
      $button.onclick = () => {
        console.log('button click');
      };
    </script>
  </body>
</html>

위의 코드와 같이 이벤트 핸들러 프로퍼티 키에 핸들러를 등록하는 방법이다.

사실 이벤트 핸들러 어트리뷰트 방식도 DOM 노드 객체의 이벤트 핸들러 프로퍼티로 변환되므로 같은 방식이라고 볼 수 있다. 이벤트 핸들러 프로퍼티는 이벤트 핸들러 어트리뷰트 방식이 가지고 있던 HTML 요소와 자바스크립트 관심사를 분리하지 못한다는 단점을 보완할 순 있으나 하나의 핸들러밖에 등록하지 못한다.

 

addEventListener 메서드 방식

<!DOCTYPE html>
<html>
  <body>
    <button>Click!</button>
    <script>
      const $button = document.querySelector('button');
      $button.addEventListener('click', () => {
        console.log('button click');
      });
    </script>
  </body>
</html>

가장 많이 사용하는 방법이다.

왜냐하면 HTML과 자바스크립트의 관심사를 분리할 수 있고, 하나 이상의 이벤트 핸들러를 등록할 수 있기 때문이다.

<!DOCTYPE html>
<html>
  <body>
    <button>Click!</button>
    <script>
      const $button = document.querySelector('button');
      $button.addEventListener('click', () => {
        console.log('button click 1');
      });
      $button.addEventListener('click', () => {
        console.log('button click 2');
      });
    </script>
  </body>
</html>

 

하지만 참조가 동일하면 하나의 핸들러만 등록된다.

<!DOCTYPE html>
<html>
  <body>
    <button>Click!</button>
    <script>
      const $button = document.querySelector('button');
      const handler = () => {
        console.log('button click');
      };
      $button.addEventListener('click', handler);
      $button.addEventListener('click', handler);
    </script>
  </body>
</html>

 

'자바스크립트' 카테고리의 다른 글

DOM과 DOM API를 통한 동적 조작  (0) 2024.03.27
네이티브 객체 vs 호스트 객체  (0) 2024.03.26
브라우저의 렌더링 과정  (0) 2024.03.25
호이스팅  (0) 2024.03.06
스코프  (0) 2024.03.03