[Javascript] Event 살펴보기

Yeojin Choi·2023년 4월 28일
0

Javascript

목록 보기
11/11

1. Event Handler

이벤트에 대응하여 실행될 핸들러(이벤트가 발생할 때 실행되는 함수)를 할당하는 방법은 3가지가 있다.

  1. HTML attribute 방식 : onclick="..."
  2. DOM property 방식 : elem.onclick = function
  3. addEventListener 방식

자세한 내용은 javascript 이벤트 핸들러 등록 방식 을 참고하자.

2. Event Object

이벤트 객체는 이벤트가 발생했을 때 생성되는 객체로, 해당 이벤트에 대한 정보를 포함한다.

이벤트 핸들러의 첫 번째 인자로 전달되며, 이벤트 핸들러 내에서 이 객체를 이용하여 이벤트 처리를 할 수 있다.

이벤트 객체에는 다양한 프로퍼티와 메소드가 있으며, 다음과 같은 정보를 제공한다.

이벤트 속성 (Event Properties)

  • target: 이벤트를 발생시킨 요소
  • type: 이벤트 유형
  • currentTarget: 현재 이벤트가 발생한 요소
  • eventPhase: 이벤트 전파 단계 (capturing, target, bubbling)
  • bubbles: 이벤트의 전파 여부
  • cancelable: 이벤트의 취소 가능 여부
  • defaultPrevented: 이벤트의 기본 동작 취소 여부
  • timeStamp: 이벤트가 발생한 시각

마우스 이벤트 추가 속성 (Mouse Event Additional Properties)

  • button: 마우스 버튼의 상태 (0: 마우스 왼쪽 버튼, 1: 마우스 중간 버튼, 2: 마우스 오른쪽 버튼)
  • clientX, clientY: 브라우저 창에서 마우스 클릭 위치
  • screenX, screenY: 전체 화면에서 마우스 클릭 위치
  • movementX, movementY: 이전 마우스 이벤트로부터의 상대적인 마우스 이동 거리

키보드 이벤트 추가 속성 (Keyboard Event Additional Properties)

  • key: 눌린 키의 값
  • keyCode: 눌린 키의 코드 (IE 9 이하에서 사용)
  • charCode: 눌린 키에 해당하는 문자의 코드
  • shiftKey, ctrlKey, altKey: Shift, Ctrl, Alt 키의 상태

포커스 이벤트 추가 속성 (Focus Event Additional Properties)

  • relatedTarget: 포커스 이전 또는 이후에 포커스를 가진 요소

스크롤 이벤트 추가 속성 (Scroll Event Additional Properties)

  • scrollLeft, scrollTop: 스크롤 위치

이외에도 다양한 이벤트 유형에 따라 각각 다른 속성과 메소드가 제공된다.

3. Event Propagation

브라우저에서 이벤트 처리 과정은 이벤트를 캡처하고 적절한 요소의 이벤트 리스너를 타겟팅하고 이벤트를 다시 DOM 트리를 거슬러 올라가며, 필요한 경우 기본 작업을 수행한다.

이벤트가 발생한 요소에서 시작하여 해당 요소의 조상 요소 또는 자손 요소로 이벤트를 전달하는 현상(이벤트 전파) 이 발생한다.

1) Event Capture

이벤트가 발생하면, 먼저 Window 객체에서 시작하여 이벤트가 발생한 실제 타겟 요소까지 DOM 트리를 따라 이벤트가 전파된다. 이 단계에서 이벤트 리스너는 capture 옵션이 true로 설정된 경우에만 실행된다.

2) Event Targeting

캡처 단계가 완료되면 이벤트는 타겟 요소에 도달하게 된다. 이 단계에서 타겟 요소에 등록된 이벤트 리스너들이 실행된다.

3) Event bubbling

이벤트가 타겟 요소의 이벤트 리스너들을 거치면, 이벤트는 다시 DOM 트리를 따라 올라가며 Window 객체까지 전달됩니다. 몇몇 이벤트들은 버블 단계가 없는 경우도 있다. (예: focus 이벤트)

이벤트 전파를 중단하려면, 이벤트 객체의 stopPropagation() 메서드를 사용하여 불필요한 이벤트 전파를 막을 수 있다.

Default Actions

이벤트 리스너에서 이벤트가 취소되지 않은 경우 브라우저는 기본 작업을 수행한다.

  • mousedown: 마우스의 버튼을 누르면 발생하는 이벤트로 select 하기 위해 마우스를 움직일때 selection 을 시작한다.
  • <input type="checkbox"> 요소에서 click: 체크박스를 클릭하면 해당 상태가 토글된다.
  • submit: <input type="submit">을 클릭하거나 폼 필드에서 Enter 키를 누르면 발생하는 이벤트로 브라우저는 폼 데이터를 서버로 제출한다.
  • keydown: 키보드에서 키를 누르면 발생하는 이벤트로 누른 키를 확인하여 해당하는 동작을 수행한다.
  • contextmenu: 오른쪽 마우스 버튼을 클릭하면 발생하는 이벤트로 일반적으로 브라우저에서 기본적으로 제공하는 메뉴를 보여준다.

이벤트의 기본 동작을 방지하려면, event.preventDefault() 또는 return false를 사용하면 된다. 두 번째 방법은 on<event>로 할당된 핸들러에만 적용된다.

4. Event Delegation

이벤트 위임(Event Delegation)은 많은 수의 하위 요소에 대한 이벤트 핸들러를 각각 등록하는 대신, 상위 요소에 하나의 이벤트 핸들러를 등록하여 하위 요소에서 발생한 이벤트를 처리하는 기법이다.

이벤트 위임은 이벤트 전파를 이용하여 구현된다. 상위 요소에 이벤트 핸들러를 등록하면, 하위 요소에서 발생한 이벤트는 상위 요소로 전파되며(Bubbling), 이벤트가 발생한 하위 요소의 정보는 이벤트 객체를 통해 전달된다. 따라서 상위 요소에서 이벤트 핸들러를 하나만 등록하면 하위 요소에서 발생한 모든 이벤트를 처리할 수 있다.

예를 들어, HTML 문서에서 리스트 항목(<li>)을 클릭하면 이벤트가 발생하는 경우, 이벤트 위임을 사용하여 상위 요소인 <ul>에 이벤트 핸들러를 등록할 수 있다. 그러면 <li> 요소에서 발생한 이벤트가 <ul> 요소까지 전파되며, 이벤트 객체를 통해 클릭한 <li> 요소의 정보를 얻어 처리할 수 있다.

<ul id="myList">
  <li>항목 1</li>
  <li>항목 2</li>
  <li>항목 3</li>
  <li>항목 4</li>
  <li>항목 5</li>
</ul>

이제 이벤트 위임을 사용하여 리스트 항목 <li>을 클릭할 때마다 해당 항목의 텍스트를 콘솔에 출력하는 코드를 작성해보면

const list = document.querySelector('#myList');

list.addEventListener('click', function(event) {
  if (event.target.tagName === 'LI') {
    console.log(event.target.textContent);
  }
});

위 코드에서는 <ul> 요소에 클릭 이벤트 핸들러를 등록한다. 이벤트 핸들러에서는 이벤트가 발생한 요소(event.target)가 <li> 요소인 경우에만 처리하도록 조건문을 사용한다. 그리고 해당 <li> 요소의 텍스트를 콘솔에 출력한다.

이렇게 하면 <ul> 요소 하위의 모든 <li> 요소에서 발생한 클릭 이벤트를 처리할 수 있다. 추가적인 <li> 요소가 동적으로 생성되어도, 위의 이벤트 핸들러에서는 새로운 항목에 대해 따로 이벤트 핸들러를 등록하지 않아도 자동으로 처리된다.

이벤트 위임은 많은 수의 요소에 대한 이벤트 핸들러를 등록하는 것보다 효율적이다. 그 이유는 이벤트 핸들러를 등록하는 것이 메모리와 성능에 부담이 되기 때문이다. 또한, 새로운 하위 요소가 추가될 때마다 해당 요소에 대한 이벤트 핸들러를 등록하는 것이 번거로울 수 있다. 이벤트 위임을 사용하면 상위 요소에서 하나의 이벤트 핸들러만 등록하면 되기 때문에 이러한 문제를 해결할 수 있다.

5. Custom Events

기본적으로 정의된 브라우저 이벤트 이외에 개발자가 직접 정의한 이벤트(Custom Event)를 생성하고 처리할 수 있다.

Custom Event를 생성하려면, 먼저 Event 또는 CustomEvent 객체를 생성한다.

CustomEvent 객체와 Event 객체의 차이 ?
: CustomEvent 객체는 Event 객체를 상속받으며, CustomEvent 객체는 detail 이라는 프로퍼티를 가지고 있어 이벤트와 함께 전달되는 추가 정보를 나타낼 수 있다!

Event 객체 사용

Event 객체 생성하기

const event = new Event(eventName, options);
const event = new CustomEvent(eventName, options);
  • eventName : 이벤트의 종류를 나타내는 문자열. "click"같은 내장 이벤트, "myEvent" 같은 커스텀 이벤트가 올 수 있다.
  • options
    • bubbles: 이벤트가 버블링될 것인지를 결정하는 boolean 값. 기본값 false
    • cancelable: 이벤트가 취소될 수 있는지를 결정하는 boolean 값. 기본값 false
    • detail: (CustomEvent 에만 존재) 이벤트와 함께 전달되는 추가 정보를 나타내는 객체. 기본값 null

Event 발생시키기

Event를 발생시키려면, element.dispatchEvent() 메소드를 사용한다.

element.dispatchEvent(event);

여기서 element이벤트가 발생하는 DOM 요소 이고, event는 위에서 생성한 Event이다.

요소에 Custom Event 핸들러 함수를 등록하기 위해서는 addEventListener() 메소드를 사용하며 이벤트의 이름을 사용자가 지정한 이름으로 사용한다.

element.addEventListener(eventName, eventHandler);

여기서 eventName은 위에서 사용자가 지정한 이벤트의 이름이며, eventHandler는 이벤트를 처리하는 콜백 함수이다.

dispatchEventaddEventListener 를 함께 사용하여 이벤트 핸들러 함수가 등록된 요소에서 이벤트가 발생할 때 실행되도록 할 수 있다.

버블링 확인 예시 코드

// 부모 요소
const parent = document.getElementById('parent');

// 자식 요소
const child = document.getElementById('child');

// 이벤트 핸들러 함수
function handleEvent(event) {
  console.log(event.target.id + ' triggered ' + event.type);
}

// 이벤트 리스너 등록
parent.addEventListener('customEvent', handleEvent);
child.addEventListener('customEvent', handleEvent);

// 이벤트 객체 생성
const customEvent = new Event('customEvent', {
  bubbles: true
});

// 이벤트 발생
child.dispatchEvent(customEvent);

// 출력 :
// child triggered customEvent
// parent triggered customEvent

위의 코드에서는 bubbles: true를 설정하여 이벤트가 버블링되도록 하였다.

  1. 이벤트를 발생시키는 대상인 child 요소에서 dispatchEvent() 메소드를 사용하여 customEvent를 발생시킨다.

  2. child 요소에서 발생한 customEvent가 처리된다.

  3. 이벤트가 버블링 되어 parent 요소에서 customEvent가 처리된다.

따라서, 이벤트가 발생한 요소에서 시작하여 부모 요소로 이벤트가 전파되는 것을 확인할 수 있다.

기본 동작 취소 예시 코드
event.preventDefault() 메서드는 기본 동작을 취소하는 메서드이다.
event.preventDefault() 를 호출하면 element.dispatchEvent(event) 호출 시 false 가 반환된다.
이는 option 의 cancelable 을 true 로 설정해 이벤트가 취소 가능하게 생성되었을 때만 적용된다.

// 버튼 요소
const button = document.getElementById('myButton');

// 이벤트 핸들러 함수
function handleCustomEvent(event) {
  event.preventDefault();
  console.log('custom event triggered');
}

// 이벤트 리스너 등록
button.addEventListener('customEvent', handleCustomEvent);

// 이벤트 객체 생성
const customEvent = new Event('customEvent', {
  // cancelable를 true로 설정하지 않으면 preventDefault가 동작하지 않는다.
  cancelable: true
});

// 이벤트 발생
const result = button.dispatchEvent(customEvent);

console.log(result); // false
profile
프론트가 좋아요

0개의 댓글