JavaScript 이벤트 기초

binu·2023년 1월 29일
0
post-thumbnail

이번 주 공부 정리할 내용은 지난 여름 프로젝트하면서 몰라서 신기했고, 아쉬웠던... 바로 그 자바스크립트 '이벤트'이다. 그때는 자바스크립트를 거의 들어만 본 상태라 html, css 작업만 했는데 그래서 아쉬웠던 기억이 있다. 이벤트 마스터는 아니고 스터디하면서 기초를 정리해본 이번 주 공부 기록이다.

이벤트란?

프로그래밍에서의 '이벤트'란 한 마디로 시스템에서 일어나는 사건을 말한다.

자주 사용되는 이벤트 타입

  • 👉 마우스 이벤트
    마우스 이벤트(mouse event) 설명
    click, doubleclick 클릭/더블 클릭
    mousedown 마우스 누를 때
    mouseup 눌렀던 마우스 땠을 때
    mouseover 요소 위로 마우스 올렸을 때
    mouseout 요소 밖으로 마우스 움직였을 때
  • 👉 포커스 이벤트
    포커스 이벤트(focus event) 설명
    focus 포커스 얻음
    blur 포커스 잃음
  • 👉 기타 이벤트
    기타 이벤트(etc event) 설명
    submit 폼 전송
    resize 사이즈 조절
    select 텍스트 선택
    scroll 스크롤 기능
    change 폼 변경

이벤트 핸들러는?

이벤트가 발생되었을 때 호출될 함수를 말한다. 예를 들어 애플리케이션이 특정 타입의 이벤트에 대해 반응해 어떤 일을 하고 싶을 때, 해당하는 타입의 이벤트가 발생하면 호출될 함수를 브라우저에게 알려 호출을 위임한다. 이때 호출되는 함수가 '이벤트 핸들러'인 것이다.

이벤트 핸들러 등록법

  • 👉 이벤트 핸들러 어트리뷰트 방식
  • : 'onclick'과 같이 접두사 'on' + 이벤트의 종류를 나타내는 '이벤트 타입'으로 구성된다. 이벤트 핸들러 어트리뷰트 값으로 함수 호출문 등의 문을 할당하면 이벤트 핸들러가 등록된다.

    /* 참고 */
    HTML과 자바스크립튼은 관심사가 다르기 때문에 이렇게 같이 사용하는 것보다는 분리하여 사용하는 것이 좋다고 한다. 하지만 오래된 코드에서 간혹 이 방식을 사용한 것이 있기 때문에 + CBD(Component Based Development) 방식의 Angular/React/Svelte/Vue.js 같은 프레임워크/라이브러리에서는 여전히 이 방식으로 이벤트를 처리하기 때문에 알아둘 필요는 있다고 한다.

  • 👉 이벤트 핸들러 프로퍼티 방식
  • 이벤트 핸들러 프로퍼티 방식 역시 이벤트 핸들러 어트리뷰트의 예시로 들었던 onclick과 같이 접두사 ‘on’과 이벤트 타입으로 이루어져있다. 단, 이벤트 핸들러 프로퍼티 방식은 HTML과 자바스크립트가 분리되므로, 이 둘이 뒤섞여 사용됨으로써 발생될 수 있는 이벤트 핸들러 어트리뷰트 방식의 문제를 해결할 수 있다. 하지만 이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 바인딩할 수 있다는 단점이 있다. (이벤트 핸들러 어트리뷰트 방식은 여러 개 바인딩할 수 있다.)

    이벤트 핸들러 프로퍼티 구성

    이미지 출처: 모던 자바스크립트 그림 40-2

    이벤트 핸들러 프로퍼티 방식으로 이벤트 핸들러를 등록하기 위해서는 이벤트를 발생시킬 객체인 이벤트 타깃(event target)과 이벤트의 종류를 나타내는 문자열인 이벤트 타입(event type), 그리고 이벤트 핸들러를 지정할 필요가 있다. 예를 들어 버튼 요소가 클릭되면 handleClick 함수를 호출하도록 이벤트를 등록하는 경우, 이벤트 타깃은 ‘버튼’ 요소이고, 이벤트 타입은 ‘click’이며, 이벤트 핸들러는 handleClick 함수이다.

  • 👉 addEventListener 메서드 방식
  • 이미지 출처: 모던 자바스크립트 그림 40-3

    addEventListener 메서드의 첫 번째 매개변수에는 이벤트의 종류를 나타내는 문자열인 이벤트 타입을 전달한다. 앞서 알아보았던 두 방식과 달리 이 방식은 접두사 ‘on’을 붙이지 않은채 이벤트 타입 문자열만을 그대로 작성한다. 두 번째 매개변수에는 이벤트 핸들러를 전달한다. 마지막 매개변수에는 이벤트를 캐치할 이벤트 전파 단계(캡처링 또는 버블링)를 지정한다. 생략하거나 false를 지정하면 버블링 단계에서 이벤트를 캐치하고, true를 지정하면 캡처링 단계에서 이벤트를 캐치한다고 한다.


이벤트 핸들러 제거

  • 👉 이벤트 핸들러 프로퍼티 방식으로 등록한 이벤트 핸들러는 ...
  •       → 이벤트 핸들러 프로퍼티에 'null'을 할당하여 제거한다.

  • 👉 addEventListener 메서드 방식으로 등록한 이벤트 핸들러는 ...
  •       → EventTarget.prototype.removeEventListener 메서도를 사용하여 제거한다.
          * 주의사항 *
          addEventListener 메서드에 전달한 인수와 removeEventListener 메서드에 전달한 인수가 일치해야 정상적인 이벤트 핸들러 등록/제거가 가능하다. (불일치하는 경우, 이벤트 핸들러 제거X)


이벤트 객체란?

  • - 이벤트가 일어나는 것 그 자체를 의미한다.
  • - 이벤트의 기능 및 속성을 제공한다.
  • ⇢ event

이벤트 전파란?

이벤트 전파란 DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파되는 것을 말한다.

위 예제는 li 요소를 클릭하면 클릭 이벤트가 발생되도록 한다. 이때 생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타깃을 중심으로 DOM 트리를 통해 전파되고, 전파되는 방향에 따라 3가지로 분류할 수 있다.

  • 캡처링 단계: 이벤트가 상위 요소에서 하위 요소 방향으로 전파 (↔️ 이벤트 버블링)
    • addEventListener의 ‘capture’ 속성은 ture로 진행됨
  • 타깃 단계: 이벤트가 이벤트 타깃에 도달
  • 버블링 단계: 이벤트가 하위 요소에서 상위 요소 방향으로 전파 (↔ 이벤트 캡처링)
    • addEventListener의 ‘capture’ 속성으로 false로 진행됨 (default 설정값임)

(+) debounce & throttle

짧은 시간 간격으로 연속해서 발생하는 이벤트(ex: scroll, resize, input, mousemove, …)를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법이다.

debounce

정의

디바운스는 짧은 시간 간격으로 발생하는 이벤트를 그룹화하여 일정 시간이 경과한 후, 마지막에 한 번만 이벤트 핸들러가 호출되도록 한다.

작동원리

debounce 함수에 두 번째 인수로 전달한 시간(delay)보다 짧은 간격으로 이벤트가 발생하면 이전 타이머를 취소하고, 새로운 타이머를 재설정한다. 따라서 delay보다 짧은 간격으로 이벤트가 연속해서 발생하면 debounce 함수의 첫 번째 인수로 전달한 콜백 함수는 호출되지 않다가, delay 동안 input 이벤트가 더 이상 발생하지 않으면 한 번만 호출된다.

(개인적으로 강의 설명이나 책 설명보다 아래 예제 코드의 가장 마지막 주석이 디바운스 작동원리를 이해하는 데에 도움이 되었다.)

언제 유용한가?

디바운스는 resize 이벤트 처리input 요소에 입력된 값으로 ajax 요청을 하는 입력 필드 자동완성 UI 구현, 버튼 중복 클릭 방지 처리 등에 유용하게 사용된다.

throttle

정의

스로틀은 짧은 시간 간격으로 연속하여 발생하는 이벤트를 그룹화하여 일정 시간 단위로 이벤트 핸들러가 호출되도록 호출 주기를 만든다.

작동원리

throttle 함수에 두 번째 인수로 전달한 시간(delay)이 경과하기 이전에 이벤트가 발생하면 아무것도 하지 않다가 delay 시간이 경과했을 때 이벤트가 발생하면 콜백 함수를 호출하고 새로운 타이머를 재설정한다. 따라서 delay 시간 간격으로 콜백 함수가 호출된다.

언제 유용한가?

스로틀은 scroll 이벤트 처리 또는 무한 스크롤 UI 구현 등에 유용하게 사용된다.


(+ 간단하게)

이벤트 루프

싱글 스레드인 자바스크립트가 동시에 여러 개를 처리할 수 있는 것처럼 보일 수 있는 것이 이벤트 루프 덕이다.

실행 컨텍스트 *

코드 실행 환경을 의미한다.



profile
예비 프론트엔드 개발자, 아기 binu

0개의 댓글