우당탕탕 개발일기

모던 자바스크립트 40. 이벤트(1) 본문

What I Learned/JavsScript

모던 자바스크립트 40. 이벤트(1)

rilee 2024. 8. 5. 11:51
728x90

1. 이벤트 드리븐 프로그래밍

  • 브라우저는 클릭, 마우스 이동 등 처리해야 할 특정 사건이 발생하면 이를 감지하여 이벤트를 발생시킨다.
  • 이벤트가 발생했을 때 호출될 함수이벤트 핸들러라고 한다.
  • 이벤트가 발생했을 때 브라우저에게 이벤트 핸들러의 호출을 위임하는 것이벤트 핸들러 등록이라고 한다.
  • 프로그램의 흐름을 이벤트 중심으로 제어하는 프로그래밍 방식을 이벤트 드리븐 프로그래밍이라고 한다.

 


2. 이벤트 타입

  • 이벤트 타입이란 이벤트의 종류를 나타내는 문자열을 의미한다.

1. 마우스 이벤트

 

2. 키보드 이벤트

 

3. 포커스 이벤트

  • focusin, focusout 이벤트는 addEventListener 메소드 방식을 사용해 등록해야 한다.
    (다른 방식으로 등록하는 경우 크롬, 사파리에서 정상 작동 X. 등록 방식에 대해선 아래에서 설명)

 

4. 폼 이벤트

 

5. 값 변경 이벤트

 

6. DOM 뮤테이션 이벤트

 

7. 뷰 이벤트

 

8. 리소스 이벤트

 


3. 이벤트 핸들러 등록

  • 이벤트가 발생했을 때 브라우저에 의해 호출되는 함수인 이벤트 핸들러.
    이러한 이벤트 핸들러의 호출을 브라우저에게 위임하는 것을 이벤트 핸들러의 등록이라고 한다.

1. 이벤트 핸들러 어트리뷰트 방식

  • HTML 요소의 어트리뷰트 중에는 이벤트에 대응하는 이벤트 핸들러 어트리뷰트가 있다.
  • 이 이벤트 핸들러 어트리뷰트의 값으로 함수 호출문 등의 문을 할당하면 이벤트 핸들러가 등록된다.
  • 이벤트 핸들러 어트리뷰트의 값은 사실 암묵적으로 생성될 이벤트 핸들러의 함수 몸체를 의미한다.

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

 

  • 이벤트 핸들러 어트리뷰트 방식은 모던 자바스크립트에선 더 이상 권장되지 않지만, React, Angular 등 프레임워크/라이브러리에서는 이와 같은 방식으로 이벤트를 처리한다.
<button onClick={handleOnClick}>저장하기</button>

 

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

  • window 객체와 Document·HTMLElement 타입의 DOM 노드 객체는 이벤트에 대응하는 이벤트 핸들러 프로퍼티를 가지고 있다.
  • 이 이벤트 핸들러 프로퍼티에 함수를 바인딩하면 이벤트 핸들러가 등록된다.

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

 

  • 이벤트 핸들러를 등록하기 위해서는 이벤트를 발생시킬 객체인 이벤트 타깃, 이벤트의 종류를 나타내는 문자열인 이벤트 타입, 이벤트 핸들러를 지정할 필요가 있다.

 

 

3. addEventListener 메소드 방식

  • addEventListener 메소드의 첫 번째 매개변수에는 이벤트 타입을, 두 번째 매개변수에는 이벤트 핸들러를, 마지막 매개변수로는 이벤트 전파 단게를 지정한다.
  • 이벤트 핸들러 프로퍼티에 이벤트 핸들러를 바인딩하는 이벤트 핸들러 프로퍼티 방식과 달리, addEventListener 메소드에는 이벤트 핸들러를 인수로 전달한다.

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

 

  • addEventListener 메소드 방식은 바인딩 된 이벤트 핸들러(=이벤트 핸들러 프로퍼티)에 아무런 영향을 주지 않는다.
  • addEventListener 메소드는 하나 이상의 이벤트 핸들러를 등록할 수 있다. 이 때 이벤트 핸들러는 등록된 순서대로 호출된다.

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

 

  • 단, addEventListener 메소드를 통해 참조가 동일한 이벤트 핸들러를 중복 등록하면 하나의 이벤트 핸들러만 등록된다.

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

 


4. 이벤트 핸들러 제거

  • addEventListener 메소드로 등록한 이벤트 핸들러를 제거하려면 EventTarget.prototype.removeEventListener 메소드를 사용한다.
  • 단, 반드시 addEventListener 메소드에 전달한 인수가 정확하게 일치해야만 이벤트 핸들러가 제거된다.
  • removeEventListener 메소드에 인수로 전달한 이벤트 핸들러는 addEventListener 메소드에 전달한 등록 이벤트 핸들러와 동일한 함수여야 한다. 무영 함수를 이벤트 핸들러로 등록한 경우 제거할 수 없다.
<!DOCTYPE html>
<html>
<body>
  	<button>Click me!</button>
	<script>
      const $button = document.querySelector('button');
      
      const handleClick = () => console.log('button click');	
      
      // 다음과 같이 무명 함수를 이벤트 핸들러로 등록한 경우 제거할 수 없다. 
      // 이벤트 핸들러를 제거하려면 이벤트 핸들러의 참조를 변수나 자료구조에 저장하고 있어야 한다.
      // $button.addEventListener('click', function (){
      //	console.log('button click');	
      // });
      
      // 이벤트 핸들러 등록
      $button.addEventListener('click', handleClick);
      
      // 이벤트 핸들러 제거 
      $button.removeEventListener('click', handleClick, true); // 인수가 일치하지 않으므로 실패
      $button.removeEventListener('click', handleClick); // 성공
    </script>
</body>
</html>
  • 이벤트 핸들러 프로퍼티 방식으로 등록한 이벤트 핸들러는 이벤트 핸들러 프로퍼티에 null을 할당하여 이벤트 핸들러를 제거한다.
<!DOCTYPE html>
<html>
<body>
  	<button>Click me!</button>
	<script>
      const $button = document.querySelector('button');
      
      const handleClick = () => console.log('button click');	
      
      // 이벤트 핸들러 프로퍼티 방식으로 이벤트 핸들러 등록
      $button.onclick = handleClick;
      
      // 이벤트 핸들러 제거 
      $button.onclick = null;
    </script>
</body>
</html>

 


5. 이벤트 객체

  • 이벤트가 발생하면 이벤트와 관련된 다양한 정보를 담고있는 이벤트 객체가 동적으로 생성된다.
  • 생성된 이벤트 객체는 이벤트 핸들러의 첫 번째 인수로 전달된다.
  • 이벤트 객체를 전달 받으려면 이벤트 핸들러를 정의할 때 이벤트 객체를 전달받을 매개변수를 명시적으로 선언해야 한다. 
  • 단, 이벤트 핸들러 어트리뷰트 방식으로 이벤트 핸들러를 등록했다면 반드시 전달받을 매개변수는 'event'여야만 한다.
    이벤트 핸들러 어트리뷰트 값은 사실 암묵적으로 생성되는 이벤트 핸들러의 함수 몸체를 의미하기 때문이다.

1. 이벤트 객체의 상속구조

  • 이벤트가 발생하면 이벤트 타입에 따라 다양한 타입의 이벤트 객체가 생성된다. 

  • Event 인터페이스에는 모든 이벤트 객체의 공통 프로퍼티가 정의되어 있고, FocustEvent 등의 하위 인터페이스에는 이벤트 타입에 따라 고유한 프로퍼티가 정의되어 있다.

 

2. 이벤트 객체의 공통 프로퍼티

  • Event 인터페이스(=Event.prototype)에 정의되어 있는 이벤트 관련 프로퍼티는 UIEvent, CustomEvent 등 모든 이벤트 객체가 상속받는 공통 프로퍼티다.

 

3. 마우스 정보 취득

  • click, mousup 등 이벤트가 발생하면 생성되는 MouseEvent 타입의 이벤트 객체는 다음과 같은 고유의 프로퍼티를 갖는다.
    1. 마우스 포인터의 좌표 정보를 나타내는 프로퍼티 : screenX/screenY, clientX/clientY, pageX/pageY, offsetX/offsetY
    2. 버튼 정보를 나타내는 프로퍼티 : altKey, ctrlKey, shiftKey, button

 

4. 키보드 정보 취득

  • keypress 등 이벤트가 발생하면 생성되는 keyBoardEvent 타입의 이벤트 객체는 altKey, ctrlKey, shiftKey, metaKey, key, keyCode 같은 고유의 프로퍼티를 갖는다.
⚠ input 요소의 입력 필드에 한글 입력 후 엔터 키 누르면 keyup 이벤트 핸들러가 두 번 호출되는 현상 발생한다.
keyup 이벤트 대신 keydown 이벤트를 캐치해야 한다.
⚠ kecode 프로퍼티는 폐지되었으므로 key 프로퍼티를 사용할 것을 권장한다.

 


6. 이벤트 전파

  • DOM 트리 상에 존재하는 DOM 요소 노드에서 발생한 이벤트는 DOM 트리를 통해 전파되는데 이를 이벤트 전파라고 한다.

  • 이벤트 전파는 이벤트 객체가 전파되는 방향에 따라 3단계로 구분된다.
    • 캡처링 단계 : 이벤트가 최상위 요소에서 시작하여 이벤트 타깃(이벤트가 실제로 발생한 요소)로 전파(하향)
    • 타깃 단계 : 이벤트가 이벤트 타깃(이벤트가 실제로 발생한 요소)에 도달
    • 버블링 단계 :  이벤트가 실제 발생한 요소에서 최상위 요소로 전파(상향)
  • 이벤트 핸들러 어트리뷰트/프로퍼티 방식으로 등록한 이벤트 핸들러는 타깃 단계와 버블링 단계의 이벤트만 캐치할 수 있다.
  • addEventListener 메소드 방식으로 등록한 이벤트 핸들러는 세 번째 인수로 true를 전달하면 캡처링 단계의 이벤트까지 캐치할 수 있다.(전달하지 않거나, false를 전달하는 경우에는 타깃 단계와 버블링 단계의 이벤트만 캐치한다.)

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

 


7. 이벤트 위임

  • 이벤트 위임이란 이벤트 전파를 활용하여 하나의 상위 DOM 요소에 이벤트 핸들러를 등록하고, 자식 요소에서 발생하는 이벤트를 처리하는 기법을 말한다.
  • 이 기법은 DOM 요소가 동적으로 생성되는 경우에 유용하다.
  • 이벤트를 실제로 발생시킨 DOM 요소와 개발자가 기대한 DOM 요소가 일치하지 않을 수 있으므로 이벤트에 반응이 필요한 DOM 요소에 한정하여 이벤트 핸들러가 실행되도록 이벤트 타깃을 검사할 필요가 있다.

 

See the Pen Untitled by Gyuri Lee (@degurrrrrr) on CodePen.

728x90