본문 바로가기

JavaScript/기본 이론

Chapter 16. 이벤트

1. 개요 

 이벤트란 웹 페이지에서 HTML 요소에 나타나는 사건을 말한다. 이벤트는 동작을 유발시키는 사건이나 대상, 이에 따른 동작과 동작에 따른 결과로 구성된다. 결과는 대부분 기능, 화면 변화를 말하며, 보이지 않는 요소의 데이터 변화 또한 결과에 해당한다.

 이벤트가 수행하는 것은 하나의 동작이기 때문에 '동적인 특성'을 가지는데, 동적인 특성을 정의한 것이기 때문에 function에서 이를 정의한다. 이벤트를 유발하는 요소는 클릭, 키 누름, 키 땜 등 다양하며, 프로그래머는 이를 적절하게 사용하여 이벤트를 정의한다.

 

2. 이벤트를 동작시키는 방법 

 이벤트를 동작시키는 방법에는 다양한 경로가 있다. 태그에 동작에 대한 속성을 정의하여 함수를 실행할 수도 있고, 혹은 자바스크립트 안에서 이벤트 리스너를 이용하여 동작을 정의할 수도 있다. 태그를 사용하여 동작을 정의하면 매개 변수를 직접 할당하여 실행하거나, 하나의 함수만 정의하여 여러 태그에 이벤트 요소를 부여할 수 있다는 장점을 가진다. 

 이벤트 리스너는 하나의 태그에 대해서 동작과 동작에 따른 참조 함수(혹은 익명 함수)를 정확하게 지정하기 때문에 onclick = "" 등을 통한 동작 정의보다 비교적 유지보수가 쉽다. 태그 하나만을 두고 비교하면 크게 차이가 없으나 태그를 동적으로 생성하고 제거하는 페이지라면 해당 요소에 직접 이벤트를 부여하는 것이 더욱 안정적이고 프로그래밍 하기 쉽다.  

 

1) 태그를 통한 이벤트 구현 

 태그에 속성을 추가하고 스크립트에 해당 동작에 대한 함수를 정의한다. 

 

 
<p onclick="changeText(this)">이 문자열을 클릭해 보세요!</p>
...
<script>
function changeText(element) {
    element.innerHTML = "문자열의 내용이 바뀌었습니다!";
}
</script>

 

 위의 예시에서 볼 수 있듯이 click이 일어나는 경우 changeText 메소드를 실행하는 것을 확인할 수 있다. 이러한 동작에는  onload, onclick, onmouseover, touch, gesture 등을 사용한다. 

 

2) 이벤트 리스너 사용 

 태그는 하나의 element node이다. element node이기 때문에 하위에 text를 포함할 수 있으며, 별개로 attribute node를 포함할 수 있다. 즉, 이벤트 리스너란 이 attribute node에 속성을 추가하는 메서드인 것이다. 때문에 태그 자체에서 이를 선언하거나, 프로퍼티로 부여하는 등 다양항 방식으로 이벤트 리스너를 사용할 수 있다.

 

① 프로퍼티로 등록 

window.onload = function() {                    // 이 함수는 HTML 문서가 로드될 때 실행됨.
    var text = document.getElementById("text"); // 아이디가 "text"인 요소를 선택함.
    text.innerHTML = "HTML 문서가 로드되었습니다.";
}

 

② 태그에 등록 

<p onclick="alert('문자열을 클릭!')">이 문자열을 클릭하면 알림창이 보인다!</p>

 

③ addEventListener("click", showText(){}) 사용

대상객체.addEventListener(이벤트명, 실행할이벤트리스너, 이벤트전파방식)


var showBtn = document.getElementById("btn"); // 아이디가 "btn"인 요소를 선택함.
showBtn.addEventListener("click", showText);  // 선택한 요소에 click 이벤트 리스너를 등록함.
function showText() {
    document.getElementById("text").innerHTML = "!!!!!! 배틀 시작 !!!!!!";
}

 

이벤트 리스너는 다수 등록하는 것이 가능하며, 태그에 대한 동작에 따라 각각 다른 결과를 출력할 수 있다. 또한 removeEventListener() 메소드를 이용해 추가된 이벤트리스너를 삭제할 수 있다. '클릭'에 대한 동작이 같은 방식으로 두번 정의되면 마지막 요소를 기준으로 하지만, 클릭외에 마우스의 이동이나 키보드 눌림 등에 대해 각각 정의되면 모두 하나의 요소에 이벤트로서 동작을 한다.

 

 

3. 이벤트 호출 순서 

 addEventListener() 메소드를 사용하면 하나의 이벤트 타입에 여러 개의 이벤트 리스너를 등록할 수 있다. 다수의 이벤트 리스너가 동작할 경우, 객체나 요소에 프로퍼티로 등록한 이벤트 리스너를 먼저 동작하고, 그 후 addEventListener() 메소드를 사용하여 등록한 이벤트 리스너를 순서대로 호출한다. 

 각기 다른 방식으로 선언된 이벤트에 동작이 겹치는 경우, 다음 순서에 따라 동작한다. 

 

  • 프로퍼티(객체가 가진 Context 속성) 에 정의된 함수 호출
  • addEventListener로 정의된 함수 (혹은 참조하는 함수) 호출

 

 

4. 이벤트 전파(event propagation)

 이벤트 전파는 이벤트가 발생했을 때, 브라우저가 이벤트 리스너를 실행시킬 대상 요소를 결정하는 과정을 말한다. 이벤트는 전파는 window와 같은 단일 객체에서는 발생하지 않지만, Document 객체나 HTML 문서 요소와 각이 복수 객체에서 발생한다. 버블링 전파 방식과 캡쳐링 전파 방식이 있는데, 버블링은 마크업 구조의 가장 안쪽에서 밖으로 이벤트 리스너가 동작하는 것이고, 캡쳐링은 가장 바깥에서 안쪽으로 이벤트 리스너가 동작하는 것이다. 

 

// 각 요소마다 버블링 방식으로 click 이벤트 리스너를 등록함.
document.getElementById("divBox").addEventListener("click", clickDiv);
document.getElementById("paraBox").addEventListener("click", clickPara);
document.getElementById("spanBox").addEventListener("click", clickSpan);
function clickDiv(event)  { document.getElementById("text").innerHTML += "div 요소를 click 하셨네요!<br>"; }
function clickPara(event) { document.getElementById("text").innerHTML += "p 요소를 click 하셨네요!<br>"; }
function clickSpan(event) { document.getElementById("text").innerHTML += "span 요소를 click 하셨네요!<br>"; }


// 각 요소마다 캡쳐링 방식으로 click 이벤트 리스너를 등록함.
document.getElementById("divBox").addEventListener("click", clickDiv, true);
document.getElementById("paraBox").addEventListener("click", clickPara, true);
document.getElementById("spanBox").addEventListener("click", clickSpan, true);
 

 

default는 버블링 방식이며, 캡처링을 사용하고 싶다면 별도로 프로퍼티를 설정해야 한다. 

 

 

5. 이벤트 기본 동작의 취소 

 HTML에는 a 태그나 input과 같이 이미 정의된 ‘이벤트 리스너’가 존재한다. 이러한 태그에 preventDefalult() 메소드나 returnValue 프로퍼티를 사용하면 기본 동작의 실행이 취소된다. 

 

// 각 요소마다 버블링 방식으로 click 이벤트 리스너를 등록함.
document.getElementById("divBox").addEventListener("click", clickDiv);
document.getElementById("paraBox").addEventListener("click", clickPara);
document.getElementById("linkBox").addEventListener("click", clickLink);
function clickDiv(event) { document.getElementById("text").innerHTML += "div 요소를 click 하셨네요!<br>"; }
function clickPara(event) { document.getElementById("text").innerHTML += "p 요소를 click 하셨네요!<br>"; }
function clickLink(event) {
    event.preventDefault(); // 링크의 기본 동작을 취소함.
    document.getElementById("text").innerHTML += "링크의 기본 동작을 막았어요!<br>";
    document.getElementById("text").innerHTML += "a 요소를 click 하셨네요!<br>";
}

 

이벤트 전파 또한 취소가 가능한데, stopPropagation() 메소드나 cancelBubble 프로퍼티를 이용하면 된다. 

 

function clickLink(event) {
    event.preventDefault();  // 링크의 기본 동작을 취소함.
    document.getElementById("text").innerHTML += "링크의 기본 동작을 막았어요!<br>";
    event.stopPropagation(); // 이벤트의 전파를 취소함.
    document.getElementById("text").innerHTML += "이벤트의 전파를 막았어요!<br>";}