[TIL] 이벤트(Event)

이벤트(Event)


이벤트 등록

이벤트 등록은 아래처럼 addEventListner() 메서드를 이용해서 가능하다.

EventTarget.addEventListener(type, handler, [options])

  • type: 이벤트의 유형

  • handler: 이벤트가 발생하면 실행될 콜백, 이벤트가 발생한 정보를 알리는 Event 객체만을 유일한 인자로 가진다.

  • options: 이벤트의 특징을 정하는 객체, 아래의 프로퍼티를 가진다.

    • capture: 어느 단계에서 이벤트를 캐치할지 정하는 프로퍼티. true캡처링, false버블링이다.

    • once: true일 경우 이벤트가 트리거 되면 자동으로 리스너가 삭제된다.

    • passive: true일 경우 핸들러로 지정한 콜백에서 절대로 preventDefault() 메서드를 호출하지 않을 것을 알린다.

  • 세 번째 매개변수인 options는 객체 대신 boolean 형태도 가능한데, 이런 경우 capture의 값을 변경하는 것과 같다.



이벤트 전파(Event Propagation)

  • 캡처링(Capturing)

    • 이벤트가 최상위 요소부터 시작하여 타깃 요소까지 아래로 전파되는 방식

    • capture 프로퍼티가 true면 캡처링 방식으로 동작한다.


  • 버블링(Bubbling)

    • 이벤트가 타깃 요소부터 시작하여 최상위 요소까지 위로 전파되는 방식

    • capture 프로퍼티가 false 혹은 3번째 인수가 없을 경우 버블링 방식으로 동작한다.


  • 이벤트의 전파는 하나만 일어나는 것이 아니라 캡처링부터 시작하여 버블링으로 종료되고, 단지 capture 프로퍼티를 통해 어느 단계에서 리스너가 실행될 지 정하는 것이다.

  • stopPropagation() 메서드를 이용해 전파를 중단할 수 있다.



이벤트 위임(Event Delegation)

이벤트가 전파되는 특성을 이용해서, 상위 요소에서 하위 요소들의 이벤트를 관리하는 방식

  • 각 요소마다 반복되는 이벤트를 추가하는 번거로움을 줄여주며, 코드도 훨씬 간결해진다.

  • 동적으로 추가된 요소에 대해서도 이벤트 처리가 가능하다.



커스텀 이벤트(Custom Event)


브라우저에서 기본적으로 제공하는 이벤트가 아닌, 직접 생성한 이벤트


이벤트 생성

Event 생성자를 이용해서 새로운 이벤트를 생성한다.

const event = new Event(type[, option])

  • type: 이벤트 타입을 나타낸다.type 은 브라우저에서 제공하는 내장 이벤트가 될 수도, my-event 같은 커스텀 이벤트가 될 수도 있다.

  • option: 이벤트의 특징을 정의한 객체

    • bubbles: boolean 타입, true인 경우 이벤트가 버블링 된다.

    • cancelable: boolean 타입, true인 경우 이벤트의 기본 동작을 차단(event.preventDefault())함을 알린다.

  • bubblescancelable 모두 false가 기본값이며, 2번째 인수가 없다면 두 프로퍼티 모두 기본값으로 처리된다.


위에서 사용한 Event() 생성자 말고도 CustomEvent() 생성자를 이용해서도 이벤트 생성이 가능하다.

const event = new CustomEvent(type[, option])

기존의 Event() 생성자와 다른 점은 option에서 객체 형태의 detail 프로퍼티를 이용해 정보를 이벤트에 전달할 수 있으며, 읽는 사람으로 하여금 명시적으로 커스텀 이벤트라는 것을 알릴 수 있다.


이벤트 실행

이벤트의 실행은 EventTarget.dispatchEvent() 메서드를 이용해서 실행한다.

EventTarget.dispatchEvent(event)

dispatchEvent() 메서드를 이용해서 버튼을 클릭하지 않고도 click 이벤트를 트리거 하는 예제를 보자.


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

      const event = new CustomEvent('click');
      setTimeout(() => {
        $button.dispatchEvent(event);
      }, 1000);      
    </script>
  </body>
</html>

버튼을 클릭하지 않아도 1초(1000ms) 뒤에 자동으로 click 이벤트가 발생한다.

내장 이벤트가 아닌, 임의의 이벤트 이름으로 변경해도 정상적으로 동작한다.


<html>
  <body>
    <button type="button">Click?</button>
    <script>
      const $button = document.querySelector('button');
      $button.addEventListener('autoClick', e => {
        console.log('Clicked!');
      });

      const event = new CustomEvent('autoClick');
      setTimeout(() => {
        $button.dispatchEvent(event);
      }, 1000);      
    </script>
  </body>
</html>

디바운싱, 쓰로틀링


쓰로틀링(Throttling)

  • 마지막으로 호출된 함수가 일정 시간이 지나기 전까지 다시 호출되지 않도록 하는 기법

  • 주로 성능을 향상시키기 위해 사용한다.


const $input = document.querySelector('input');
let timer = null;

$input.addEventListener('input', e => {
  const { value } = e.target;

  if (!timer) {
    timer = setTimeout(() => {
      console.log(value);
      timer = null;
    }, 500);
  }
});


디바운싱(Debouncing)

  • 여러 차례 호출 된 함수들 중, 마지막 함수만 호출하는 기법

  • 주로 API와의 통신 횟수를 줄이려 할 때 사용한다.


const $input = document.querySelector('input');
let timer = null;

$input.addEventListener('input', e => {
  const { value } = e.target;

  if (timer) {
    clearTimeout(timer);
  }

  timer = setTimeout(() => {
    console.log(value);
  }, 500);
});



UI 렌더링


비관적 렌더링(Pessimistic Rendering) 흐름

  • 이벤트 발생

  • 서버로 정보 변경 요청

  • 요청에 대한 서버 응답

  • 응답을 기반으로 상태 변경 및 렌더링


낙관적 렌더링(Optimistic Rendering) 흐름

  • 이벤트 발생

  • 서버에게 전달할 요청이 성공적으로 처리되었다고 확신, 미리 상태 변경 및 렌더링

  • 서버로 정보 변경 요청

  • 요청 실패 시 이전 상태로 되돌림





참고 자료

Event | PoiemaWeb

EventTarget.addEventListener() | MDN

Event() - Web API | MDN

브라우저 이벤트 소개 | 모던 JS 튜토리얼

커스텀 이벤트 디스패치 | 모던 JS 튜토리얼

쓰로틀링과 디바운싱 | Zerocho

Optimistic and Pessimistic UI Rendering Approaches | Medium

좋은 웹페이지 즐겨찾기