본문 바로가기
언어 Language/자바스크립트 JavaScript

[JavaScript] 이벤트 (1) - 이벤트(event)의 개념과 사용법

by 이땡칠 2022. 6. 14.

 

요약

1. 이벤트는 우리가 프로그래밍하고 있는 시스템에서 일어나는 사건(action) 혹은 발생(occurrence)이다.

2.  이벤트가 발생되면 실행되는 코드 블럭을 이벤트 핸들러 또는 이벤트 리스너라고 하며, 이 코드블럭이 이벤트에 응답해서 실행하도록 정의하는 것을 이벤트 핸들러를 등록 했다고 표현한다.

3. 웹 이벤트를 사용하는 방법은 3 가지가 있다.
 1) 이벤트 핸들러 프로퍼티 
 2) 인라인 이벤트 핸들러
 (사용 권장x)  
  - html 태그에 이벤트 핸들러(자바스크립트 코드) 가 직접 기술된다는 점이 단점이다. 
  - html 은 정보를 표현하기 위한 수단. 제어와 관련된 것은 javascript 로 분리시키는 것이 좋다.
  
 3) addEventListener()  removeEventListener() 메서드 사용 (이벤트 핸들러 추가 제거)
  (사용 권장)
   - removeEventListener()을 사용하여 이벤트 핸들러 코드를 삭제할 수 있다.
   - 만약 요구된다면 같은 타입의 다수의 리스너를 요소들에 추가할 수 있다.

4. "3"의 3 가지 메커니즘 중에서 1), 3) 을 사용할 수 있는데, 
 - 이벤트 핸들러 프로퍼티는 더 적은 능력과 옵션을 가지고 있지만, 더 나은 크로스 브라우저 호환성을 가지고 있다. (Internet Explorer 8만큼 옛날 브라우저에서도 지원됨). 
 - DOM Level 2 이벤트 (addEventListener() 등)은 더욱 강력하지만, 또한 복잡하며 덜 지원된다. (Internet Explorer 9만큼 옛날 브라우저에서 지원됨). 

 

 

이벤트 개념 

이벤트(event)란 우리가 프로그래밍하고 있는 시스템에서 일어나는 사건(action) 혹은 발생(occurrence)입니다.

시스템은 이벤트가 발생될 때 몇몇 종류의 신호를 생산(produce) (또는 "발생(fire)"시키고, 이벤트가 발생되었을 때 사건이 자동적으로 취해질 수 있는 메커니즘 (즉, 코드의 실행)을 제공합니다.

 

예를 들자면, 공항에서, 활주로가 이륙을 위해 막혀 있지 않을 때, 신호가 파일럿에게 전달됩니다.

결과적으로, 비행기는 안전하게 이륙할 수 있습니다.

 

 

 

웹의 경우에, 이벤트는 브라우저 윈도우 내에서 발생되고, 그것이 거주하는 특정한 요소에 부착되는 경향이 있습니다 — 이것은 하나의 요소, 요소들의 집합, 현재 탭에 로드된 HTML 문서, 혹은 전체 브라우저 윈도우일지도 모릅니다. 발생될 수 있는 많은 각양각색의 이벤트 타입이 있습니다. 예를 들자면:

 

  • 유저가 어떤 요소를 선택하거나 어떤 요소 위에 커서를 올려둡니다(hover).
  • 유저가 키보드에서 키를 선택합니다.
  • 유저가 브라우저 창의 크기를 재조정하거나 닫습니다.
  • 웹 페이지가 로딩을 완료했습니다.
  • 양식(form)이 제출되었습니다.
  • 비디오가 재생되거나, 멈추거나, 혹은 끝났습니다.
  • 오류가 발생했습니다.

이벤트 헨들러

각각의 이용가능한 이벤트들은 이벤트 핸들러(event handler)를 가지고 있는데, 이는 이벤트가 발생되면 실행되는 코드 블럭 (프로그래머가 만드는 JavaScript 함수)입니다. 

 

그러한 코드 블럭이 이벤트에 응답해서 실행되기 위해 정의되었을 때, 우리는 이벤트 핸들러를 등록(register)했다고 말합니다.

 

참고 

이벤트 핸들러는 때때로 이벤트 리스너(event listener)라고 불립니다. 이것들은 우리의 목적을 위해 꽤 교체할수 있지만, 그러나 엄밀히 말하자면, 그들은 같이 동작합니다. 리스너는 발생되는 이벤트에 대해 듣고, 핸들러는 발생되는 이벤트에 응답해서 실행되는 코드입니다.

 

예제

const btn = document.querySelector('button');

function random(number) {
  return Math.floor(Math.random() * (number+1));
}

btn.onclick = function() {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}

이 코드에서, Document.querySelector() 함수를 사용하여, 우리는 btn 상수 내부에 버튼에 대한 참조를 저장했습니다.

우리는 또한 무작위의 숫자를 반환하는 함수를 정의했습니다. 코드의 세번째 부분은 이벤트 핸들러입니다.

btn 상수는 <button> 요소를 가리키고, 이 타입의 객체는 발생시킬 수 있는 얼마간의 이벤트를 가지고 있으므로,

이벤트 핸들러를 사용 가능합니다. onclick 이벤트 핸들러 프로퍼티를 무작위의 RGB 색상을 생성하고 그것과 같은  <body> background-color를 설정하는 코드를 포함하는 익명함수에 설정함으로써,

우리는 click 이벤트 발생에 귀를 기울이고 있습니다.

 

이 코드는 언제든지 <button> 요소에서 click 이벤트가 발생될 때, 즉 언제든지 유저가 그것을 선택했을 때, 실행됩니다.

 

 

참고

 웹 이벤트는 코어 JavaScript 언어의 일부가 아닙니다. 이것들은 브라우저에 내장된 API의 일부로서 정의됩니다.

대부분의 프로그래밍 언어는 몇몇 종류의 이벤트 모델을 가지고 있고, 그 모델이 작동하는 방식은 종종 JavaScript의 방법과는 다릅니다.

일단은 이벤트가 다른 프로그래밍 환경에서 다를 수 있다는 것만 기억하면 됩니다. 

웹 이벤트를 사용하는 방법들

이벤트 핸들러 프로퍼티

const btn = document.querySelector('button');

btn.onclick = function() {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}

 

onclick 프로퍼티는 이 상황에서 쓰이고 있는 이벤트 핸들러 프로퍼티입니다. 이것은 본질적으로 버튼에서 사용 가능한 다른 것들과 같은 프로퍼티지만 (예: btn.textContent, 또는 btn.style), 이것은 특별한 타입입니다 — 어떤 코드와 동일한 것을 설정했을 때, 그 코드는 버튼에서 이벤트가 발생되었을 때 실행됩니다.

 

여러분은 또한 기명 함수 이름과 같은 핸들러 프로퍼티를 설정할 수 있습니다 (자신만의 함수 만들기에서 본 것처럼요). 다음은 아주 똑같이 동작합니다:

 

const btn = document.querySelector('button');

function bgChange() {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}

btn.onclick = bgChange;

 

몇몇 이벤트들은 일반적이고 거의 어디서나 사용 가능한 반면 (예: onclick 핸들러는 거의 어떠한 요소에서도 등록될 수 있습니다), 몇몇은 더욱 특수하고 오직 어떤 상황들에서만 유용합니다 (예: onplay를 오직 <video>와 같은, 특정한 요소에서만 사용하는 것은 타당합니다).

 

 

인라인 이벤트 핸들러 — 사용하지 마세요

<button onclick="bgChange()">Press me</button>

function bgChange() {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}

웹에서 찾아지는 가장 이른 이벤트 핸들러의 등록 방법은 위에서 보이는 것처럼 이벤트 핸들러 HTML 어트리뷰트 (또는 인라인 이벤트 핸들러)을 포함합니다. — 어트리뷰트 값은 말 그대로 이벤트가 발생되었을 때 여러분이 실행하기를 원하는 JavaScript 코드입니다. 위의 예시는 같은 페이지의 <script> 요소 안에서 정의된 함수를 호출하지만, 여러분은 또한 어트리뷰트 안에 직접적으로 JavaScript을 삽입할 수 있습니다. 예를 들자면:

 

<button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button>

 

여러분은 HTML 어트리뷰트를 많은 이벤트 핸들러 프로퍼티와 동등한 것이라고 생각할 수도 있습니다; 그러나, 여러분은 이 방법을 사용해서는 안 됩니다 — 이 방법은 나쁜 습관이라고 여겨집니다. 만약 여러분이 뭔가를 정말 빨리 한다면 이벤트 핸들러 어트리뷰트를 사용하는 것이 쉬워 보일지도 모르나, 이것은 빠르게 다루기 힘들어지고 비효율적이 됩니다.

 

우선, HTML과 JavaScript를 뒤죽박죽으로 만드는 것은 좋은 생각이 아닙니다. 왜냐하면 분석하기(parse)가 어려워지기 때문입니다 — JavaScript를 분리한 채로 놔두는 것이 좋은 습관입니다; 만약 이것이 분리된 파일 안에 있다면 여러분은 이것을 다수의 HTML 문서에 적용할 수 있습니다.

 

 

하나의 파일이더라도, 인라인 이벤트 핸들러는 좋은 생각이 아닙니다. 하나의 버튼은 괜찮지만, 100개의 버튼이라면 어떡할 건가요? 여러분은 파일에 100개의 어트리뷰트를 더해야만 합니다; 이것은 빠르게 유지보수의 악몽으로 변할 것입니다.

 

 

이벤트 핸들러를 추가하고 제거하기

이벤트 핸들러를 더하는 현대적인 메커니즘은 addEventListener() 메서드입니다. 이것을 사용해서, 우리는 무작위 색상 예제를 다음과 같이 재작성할 수 있습니다.

 

const btn = document.querySelector('button');

function bgChange() {
  const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}

btn.addEventListener('click', bgChange);

 

addEventListener() 함수 안에, 우리는 두 매개변수(parameter)를 명시합니다: 우리가 이 핸들러에 등록하고자 하는 이벤트의 이름과, 그것에 응답하여 우리가 실행하기를 원하는 핸들러 함수를 구성하는 코드입니다. 알림: addEventListener() 내부에, 다음과 같이, 익명 함수 안에 모든 코드를 넣는 것은 완벽히 괜찮습니다:

 

btn.addEventListener('click', function() {
  var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
});

 

이 메커니즘은 앞에서 논한 낡은 메커니즘들에 비해 몇몇 이점을 가지고 있습니다. 첫째로, 이전에 추가한 이벤트 핸들러를 제거하는, removeEventListener()라는 대응 관계에 있는 함수가 있습니다. 예를 들어, 이것은 이 섹션의 첫번째 코드 블록 안에 있는 이벤트 핸들러를 제거할 것입니다.

 

btn.removeEventListener('click', bgChange);

 

이벤트 핸들러는 또한 AbortSignal addEventListener()에 전달하고, 그리고서 나중에, AbortSignal을 소유하고 있는 컨트롤러에서 abort()를 호출함으로써 제거할 수도 있습니다. 예를 들자면, 우리가 AbortSignal로 제거할 수 있는 이벤트 핸들러를 추가하기 위해서는:

 

const controller = new AbortController();
btn.addEventListener('click', function() {
  var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
  document.body.style.backgroundColor = rndCol;
}, { signal: controller.signal }); // 이 핸들러에 AbortSignal을 전달

 

그리고서 위의 코드로 생성된 이벤트 핸들러는 다음과 같이 제거될 수 있습니다:

 

controller.abort(); // 이 컨트롤러와 연관된 어떠한/모든 이벤트 핸들러를 제거

 

간단하고, 작은 프로그램에 대해서는, 낡고, 사용되지 않는 이벤트 핸들러를 청소하는 것은 필수적이지 않습니다 — 하지만 더 크고, 더욱 복잡한 프로그램에 대해서는, 이것은 효율성을 향상시킬 수 있습니다. 더해서, 이벤트 핸들러를 제거할 수 있는 능력은 같은 버튼이 다른 상황에서 다른 작동을 수행하도록 하는 것을 가능케 합니다.

 

앞서 논한 낡은 메커니즘에 대해 addEventListener() 가 가지고 있는 두 번째 이점은 같은 리스너에 대해 다수의 핸들러를 등록하는 것을 가능하게 한다는 것입니다. 다음의 두 핸들러는 둘 다 적용되지 않을 것입니다:

 

myElement.onclick = functionA;
myElement.onclick = functionB;

 

두 번째 줄이 첫 번째 줄에 의해 설정된 onclick의 값을 덮어씁니다. 그러나, 다음은 작동할 것입니다.

myElement.addEventListener('click', functionA);
myElement.addEventListener('click', functionB);
 

두 함수 모두는 이제 요소가 선택되었을 때 실행될 것입니다.

댓글