40. 이벤트
2025. 1. 6. 16:47ㆍ기록/Modern JavaScript Deep Dive
이벤트 드리븐 프로그래밍
이벤트 핸들러
- 이벤트가 발생했을 때 호출될 함수
이벤트 핸들러 등록
- 이벤트가 발생했을 때 브라우저에게 이벤트 핸들러의 호출을 위임하는 것
이벤트 드리븐 프로그래밍
- 이벤트와 그에 대응하는 함수(이벤트 핸들러)를 통해 사용자와 애플리케이션은 상호작용을 할 수 있음
- 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식
이벤트 타입
마우스 이벤트
이벤트 타입 | 이벤트 발생 시점 |
click | 마우스 버튼을 클릭했을 때 |
dbclick | 마우스 버튼을 더블 클릭했을 때 |
mousedown | 마우스 버튼을 눌렀을 때 |
mouseup | 누르고 있던 마우스 버튼을 놓았을 때 |
mousemove | 마우스 커서를 움직였을 때 |
mouseenter | 마우스 커서를 HTML 요소 안으로 이동했을 때 (버블링 X) |
mouseover | 마우스 커서를 HTML 요소 안으로 이동했을 때 (버블링 O) |
mouseleave | 마우스 커서를 HTML 요소 밖으로 이동했을 때 (버블링 X) |
mouseout | 마우스 커서를 HTML 요소 밖으로 이동했을 때 (버블링 O) |
키보드 이벤트
keydown | 모든 키를 눌렀을 때 |
keypress | 문자 키를 눌렀을 때 연속적으로 발생 (deorecated 되었으므로 사용하지 않을 것을 권장함) |
keyup | 누르고 있던 키를 놓았을 때 한 번만 발생 |
포커스 이벤트
focus | HTML 요소가 포커스를 받았을 때 (버블링 X) |
blur | HTML 요소가 포커스를 잃었을 때 (버블링 X) |
focusin | HTML 요소가 포커스를 받았을 때 (버블링 O) / addEventListener 메서드 방식을 사용해야함 |
focusout | HTML 요소가 포커스를 잃었을 때 (버블링 O) / addEventListener 메서드 방식을 사용해야함 |
폼 이벤트
submit | 1. form 요소 내의 input(text, checkbox, radio), select 입력 필드(textarea 제외)에서 엔터키를 눌렀을 때 2. form 요소 내의 submit 버튼을 클릭했을 때 |
값 변경 이벤트
input | input, select, textarea 요소의 값이 입력되었을 때 사용자가 입력을 하고 있을 때 발생 |
change | input, select, textarea 요소의 값이 입력되었을 때 사용자 입력이 종료되어 값이 변경될 때 발생 (해당 요소가 포커스를 잃었을 때) |
readystatechange | HTML 문서의 로드/파싱 상태를 나타내는 document.readyState 프로퍼티 값 ('loading', 'interactive', 'complete')이 변경될 때 |
DOM 뮤테이션 이벤트
DOMContentLoaded | HTML 문서의 로드/파싱이 완료되어 DOM 생성이 완료되었을 때 |
뷰 이벤트
resize | 브라우저 윈도우의 크기를 리사이즈할 때 연속적으로 발생 |
scroll | 웹페이지 또는 HTML 요소를 스크롤할 때 연속적으로 발생 |
리소스 이벤트
load | DOMContentLoaded 이벤트 발생 후, 모든 리소스의 로딩이 완료되었을 때 (주로 window 객체에서 발생) |
unload | 리소스가 언로드될 때 (주로 새로운 웹페이지 요청 시) |
abort | 리소스 로딩이 중단되었을 때 |
error | 리소스 로딩이 실패했을 때 |
이벤트 핸들러 등록
1. 이벤트 핸들러 어트리뷰트 방식
<button onclick="sayHi('Lee')">Click Me!</button>
...
function sayHi(name) {
console.log(`Hi! ${name}!`);
}
- on 접두사 사용
- 함수 참조를 등록해야 브라우저가 이벤트 핸들러 호출 가능
- 함수 호출문을 등록하면 함수 호출문의 평과 결과가 이벤트 핸들러로 등록됨
2. 이벤트 핸들러 프로퍼티 방식
buttonEl.onclick = function () {
console.log('click!');
};
- 이벤트 타깃.on+이벤트타입 = 이벤트핸들러
- 이벤트 타깃: 이벤트를 발생시킬 객체
- 이벤트 타입: 이벤트의 종류를 나타내는 문자열
- 이벤트 핸들러: 함수
- 이벤트 핸들러 프로퍼티에 하나의 이벤트 핸들러만 바인딩 가능
3. addEventListener 메서드 방식
EventTarget.addEventListener('eventType', functionName [, useCapture]);
- 첫 번째 매개변수: 이벤트의 종류를 나타내는 문자열인 이벤트 타입 전달 (on 접두사 X)
- 두 번째 매개변수: 이벤트 핸들러 전달
- 마지막 매개변수: 이벤트를 캐치할 이벤트 전파 단계 지정
- 생략/false 시 버블링 단계에서 이벤트 캐치
- true 시 캡쳐링 단계에서 이벤트 캐치
- 하나 이상의 이벤트 핸들러 등록 가능 (등록 순서대로 호출됨)
이벤트 핸들러 제거
addEventListener 메서드로 등록한 이벤트 핸들러 제거
- removeEventListener 메서드 사용
- addEventListener 메서드에 전달한 인수와 removeEventListener 메서드에 전달한 인수가 일치해야 제거됨
이벤트 핸들러 프로퍼티 방식으로 등록한 이벤트 핸들러 제거
- 이벤트 핸들러 프로퍼티에 null 할당
이벤트 객체
function handleClick (event) {
console.log(event);
}
- 이벤트 발생 시 이벤트 객체가 동적으로 생성되고 이벤트 핸들러의 첫 번째 인수로 전달됨
- 이벤트 핸들러 어트리뷰트 방식일 경우
- 이벤트 핸들러의 첫 번째 매개변수 이름이 event 이어야 이벤트 객체를 전달받을 수 있음
이벤트 객체의 공통 프로퍼티
공통 프로퍼티 | 설명 | 타입 |
type | 이벤트 타입 | string |
target | 이벤트를 발생시킨 DOM 요소 | DOM 요소 노드 |
currentTarget | 이벤트 핸들러가 바인딩된 DOM 요소 | DOM 요소 노드 |
eventPhase | 이벤트 전파 단계 0: 이벤트 없음 1: 캡쳐링 단계 2. 타깃 단계 3. 버블링 단계 |
number |
bubbles | 이벤트를 버블링으로 전파하는지 여부 버블링 불가능한 이벤트 focus / blur / load / unload / abort error / mouseenter / mouseleave |
boolean |
cancelable | preventDefault 메서드를 호출하여 이벤트의 기본 동작을 취소할 수 있는지 여부 취소 불가능한 이벤트 focus / blur / load / unload / abort error / dbclick / mouseenter / mouseleave |
boolean |
defaultPrevented | preventDefault 메서드를 호출하여 이벤트를 취소했는지 여부 | boolean |
isTrusted | 사용자의 행위에 의해 발생한 이벤트인지 여부 (click 메서드 / dispatchEvent 메서드를 통해 인위적으로 발생시킨 이벤트일 경우 false) |
boolean |
timeStamp | 이벤트가 발생한 시각 (1970/01/01/00:00:0 부터 경과한 밀리초) | number |
마우스 정보 취득
마우스 이벤트가 발생하면 생성되는 MouseEvent 타입의 이벤트 객체는
아래와 같은 고유의 프로퍼티를 가짐
마우스 포인터의 좌표 정보를 나타내는 프로퍼티
- screenX/screenY, clientX/clientY, pageX/pageY, offsetX/offsetY
버튼 정보를 나타내는 프로퍼티
- altKey, ctrlKey, shiftKey, button
키보드 정보 취득
키보드 이벤트가 발생하면 생성되는 keyboardEvent 타입의 이벤트 객체는
altKey, ctrlKey, shiftKey, metaKey, key, keyCode(폐지) 같은 고유의 프로퍼티를 가짐
이벤트 전파
DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트가 DOM 트리를 통해 전파되는 것
이벤트 객체가 전파되는 방향에 따라 3단계로 구분 가능
캡쳐링 단계
- 이벤트가 상위요소에서 하위 요소 방향으로 전파
- window -> document -> html -> body -> ul -> li
타깃 단계
- 이벤트가 이벤트 타깃에 도달
- li
버블링 단계
- 이벤트가 하위 요소에서 상위 요소 방향으로 전파
- li -> ul -> body -> html -> document -> window
이벤트 핸들러 어트리뷰트/프로퍼티 방식으로 등록한 이벤트 핸들러
- 타깃 단계, 버블링 단계의 이벤트만 캐치 가능
addEventListener 메서드 방식으로 등록한 이벤트 핸들러
- 타깃 단계, 버블링 단계, 캡쳐링 단계 이벤트 모두 캐치 가능
이벤트 위임
여러 개의 하위 DOM 요소에 각각 이벤트 핸들러를 등록하는 대신
하나의 상위 DOM 요소에 이벤트 핸들러를 등록하는 방법
이벤트에 반응이 필요한 DOM 요소에 한정하여 이벤트 핸들러가 실행되도록 이벤트 타깃을 검사해야 함
DOM 요소의 기본 동작 조작
- DOM 요소는 기본 동작을 가지고 있음 (a태그 클릭 시 href 어트리뷰트에 지정된링크로 이동 등)
- 이벤트 객체의 preventDefault 메서드는 DOM 요소의 기본 동작을 중단시킴
- 이벤트 객체의 stopPropagation 메서드는 이벤트 전파를 중지시킴
이벤트 핸들러 내부의 this
이벤트 핸들러 어트리뷰트 방식
<button onclick="handleClick()">Click Me</button>
...
function handleClick() {
console.log(this); // window
}
- 일반 함수로 호출되는 함수 내부의 this 는 전역 객체를 가리킴 (window)
<button onclick="handleClick(this)">Click Me</button>
...
function handleClick(button) {
console.log(button); // 이벤트를 바인딩한 button 요소
console.log(this); // window
}
- 이벤트 핸들러를 호출할 때 인수로 전달한 this 는 이벤트를 바인딩한 DOM 요소를 가리킴
이벤트 핸들러 프로퍼티 방식 / addEventListener 메서드 방식
- 이벤트 핸들러 내부의 this 는 이벤트를 바인딩한 DOM 요소를 가리킴 (=== 이벤트 객체의 currentTarget)
- 화살표 함수로 정의한 이벤트 핸들러 내부의 this 는 상위 스코프의 this 를 가리킴