웹에서 이벤트(Event)란, 간단히 말해 브라우저에서 어떤 사건이 일어났다는 것입니다. 이 사건에는 클릭, 마우스 이동, 스크롤과 같이 유저가 만들어내는 이벤트부터 로딩 완료, 애니메이션 종료 등 브라우저에서 자동으로 발생되는 사건까지 다양한 타입의 이벤트가 포함됩니다.
자주 사용되는 이벤트 타입들과, 언제 발생하는지에 대해 알아봅시다.
브라우저에서 이벤트가 발생했을 때, 우리는 JS를 이용해 그 이벤트를 활용하거나 대응할 수 있습니다. 그 방법에는 이벤트 핸들러와 이벤트 리스너가 있는데요, 비슷하면서 다른 두 가지 방법에 대해 알아보겠습니다.
브라우저에서 어떤 이벤트가 발생하면, 우리는 그 이벤트에 대응할 함수를 등록 (register) 할 수 있습니다. 예를 들어, 어떤 버튼을 클릭했을 때 콘솔에 메시지를 출력하도록 하는 코드를 한 번 볼까요?
<!-- HTML -->
<button id="my-button">버튼</button>
//JavaScript
const myButton = document.getElementById("my-button");
myButton.onclick = () => {
console.log("Button clicked");
};
위의 JS 코드에서는 id 가 “my-button” 인 요소에 onclick
핸들러를 등록합니다. 어떤 요소에 onclick
이벤트 핸들러 함수가 등록되면, 해당 요소가 클릭되었을 때 등록된 함수가 작동합니다. 예제에서는 이벤트 핸들러를 화살표 함수 () ⇒ {} 형식으로 등록했지만, 새로운 함수를 정의한 뒤 등록할 수도 있습니다.
또는, 아래와 같이 html 요소에 인라인 이벤트 핸들러 형식으로 등록할 수도 있습니다. (권장되지는 않는 방법입니다.)
<!-- 간단한 이벤트 핸들러 등록 -->
<button id="my-button" onclick="console.log('Button clicked')">버튼</button>
이벤트 핸들러의 근본적인 문제 중 하나는, 하나의 이벤트에 여러 개의 핸들러를 등록할 수 없다는 것입니다.
그래서 addEventListener
와 removeEventListener
라는 메소드가 만들어졌고, 이 메소드들을 사용해 이벤트를 관리하는 것이 조금 더 현대적인 방식입니다.
addEventListener
사용법element.addEventListener(event, handler, [options]);
[option]
인자는 이벤트를 어떤 방식으로 핸들링할지 설정할 수 있는 인자입니다. 핸들러 함수를 한 번만 호출하도록 하거나, 이벤트 도중에 호출하도록 설정할 수 있습니다.
아까 봤던의 myButton 예제를 사용법에 맞게 addEventListener
방식으로 바꾸면 아래와 같습니다.
myButton.addEventListener("click", () => console.log("Button clicked"));
같은 방식으로 removeEventListener
를 사용하면 등록된 함수를 삭제할 수 있습니다.
브라우저에서 이벤트가 발생되면, 이벤트 객체가 생성됩니다. 이벤트 객체에는 해당 이벤트에 대한 상세한 정보가 담겨 있으며, 핸들러 함수에 인수 형태로 전달됩니다. 이벤트 객체는 아래와 같은 방식으로 콘솔에서 확인할 수 있습니다.
myButton.onclick = function(event) {
console.log(event);
}
이벤트 객체에는 이벤트가 발생한 대상, 위치, 시간 뿐만 아니라 다양한 정보가 담겨져 있습니다. 위 코드를 사용해 직접 확인해 보세요.
브라우저의 이벤트 흐름은 캡처링 단계 - 타깃 단계 - 버블링 단계의 3단계로 이루어집니다. 브라우저의 최상위 요소로부터 타깃 요소까지 이벤트가 먼저 전파되고, 타깃 요소에서 이벤트가 발생한 뒤, 다시 상위 요소로 버블링이 일어납니다. 이 흐름을 생각하고 아래 개념을 보겠습니다.
이벤트 버블링이란, 중첩된 요소들에 등록된 핸들러들이 자식 요소부터 부모 요소까지 순차적으로 모두 동작하는 것입니다. 아래 html 을 볼까요?
<form onclick="alert('form')">FORM
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
</form>
form 안의 div, 그안의 p 태그가 중첩되어 있습니다. 이때 p 태그를 클릭하면 가장 먼저 p 경고창이 나타나고, 그 뒤에 div와 form 경고창이 순서대로 나타납니다. 이런 이벤트 발생 흐름을 바로 ‘이벤트 버블링’이라고 합니다.
이런식으로 버블링이 발생하면, 어떤 핸들러를 작동시켰을 때 의도하지 않은 핸들러가 작동될 수도 있겠죠? 버블링을 막기 위해서는 이벤트 전달을 중단시키는 stopPropagation
메소드를 사용하면 됩니다.
이 메소드는 이벤트를 완전히 처리하고 난 후 버블링을 중단해, 상위 요소로 이벤트가 전달되지 못하도록 합니다.
💡 버블링은 유용하게 사용됩니다. 꼭 버블링을 막아야 하는 상황이 아니면 버블링을 막지 않는 것이 좋아요!캡처링은 버블링과 반대로, 상위 요소부터 이벤트의 타깃 요소까지 전파되는 흐름입니다. 캡처링 단계에서 이벤트를 잡아내는 것은 자주 사용되지는 않지만, 만약 사용할 경우 addEventListener
에서 capture: true
옵션을 설정해야 합니다.