이벤트 핸들러 프로퍼티와 addEventListener 메서드의 차이점

이벤트 핸들러는 이벤트가 발생했을 때 브라우저에 호출을 위임한 함수입니다. 이벤트가 발생하면 자바스크립트 엔진은 브라우저에게 이벤트 핸들러의 호출을 위임하게 하는 것을 이벤트 핸들러 등록이라고 합니다. 이벤트 핸들러를 등록하는 방법은 총 3가지입니다. ‘이벤트 핸들러 어트리뷰트 방식’, ‘이벤트 핸들러 프로퍼티 방식’, ‘addEventListener 방식’으로 이벤트 핸들러를 등록합니다.

이벤트 핸들러 어트리뷰트 방식은 오래된 코드에서 간혹 확인해볼 수 있기 때문에 이런 것이 있다고만 알아두는 것이 좋습니다. HTML과 자바스크립트는 마크업과 Interection이라는 서로 다른 관심사를 가지고 있기 때문에 혼재하는 것보다는 분리하는 것이 좋습니다. 이번 포스팅에서는 자바스크립트 내에서 핸들러를 등록하는 두가지 방식을 중점적으로 비교하겠습니다.


이벤트 핸들러 등록

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

위에 서술한대로 예전 DOM level0 때나 관심사의 분리를 통한 웹 구성을 하기 이전의 레거시 코드로 남아있는 경우가 많습니다. 그러나 모던 자바스크립트에서는 이벤트 핸들러 어트리뷰트 방식을 사용하는 경우가 있기 때문에 알아둘 필요는 있습니다.

1
2
3
4
<!--Angular -->
<button (click)="handleClick($event)">button</button>
{ /* React */}
<button onClick="handleClick($event)">button</button>

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

DOM 노드 객체는 이벤트에 대응하는 이벤트 핸들러 프로퍼티를 가지고 있으며, onclick과 같이 on 접두사와 이벤트의 종류를 나타내는 이벤트 타입으로 이루어져있습니다. 이벤트 핸들러를 등록하기 위해 이벤트를 발생시킬 대상 (이벤트 타깃)과 이벤트의 종류 (이벤트 타입) 그리고 이밴트 핸들러를 지정해주어야 합니다.

1
2
3
$button.onclick = () => {
console.log("Clicked!");
};

addEventListener 메서드 방식

DOM Level 2에서 도입된 addEventListener 메서드 방식은 메서드를 사용하여 이벤트 핸들러를 등록할 수 있습니다. 첫번째 매개변수로 이벤트의 종류를 나타내는 이벤트 타입, 두번째 매개변수로 이벤트 핸들러를 전달합니다. 마지막 매개변수에는 이벤트를 캐치할 이벤트 전파단계를 지정합니다. 생략하거나 false를 지정하면 버블링 단계에서 이벤트를 캐치하고, true를 지정하면 캡처링 단계에서 이벤트를 캐치합니다.

1
2
3
4
5
const $button = document.querySelector("button");

$button.addEventListener("click", (e) => {
console.log(e);
});

이벤트 핸들러 프로퍼티와 addEventListener 메서드의 차이점

스크립트 내에서 이벤트를 등록하는 두 방식에는 이벤트의 누적 여부, 이벤트 전파 정의 등의 차이가 있습니다.

이벤트 누적 여부

이벤트 핸들러 프로퍼티는 이벤트 객체를 하나만 등록 가능합니다. 만약 2개의 이벤트 핸들러를 등록하게 되면 가장 마지막에 추가한 이벤트 핸들러가 이전 이벤트 핸들러를 덮어쓰게 됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const $test = document.getElementById("test");

const func1 = () => {
console.log("test1");
};
const func2 = () => {
console.log("test2");
};
const func3 = () => {
console.log("test3");
};

$test.onclick = func1;
$test.onclick = func2;
$test.onclick = func3;

그러나 addEventListener 메서드 방식의 경우 이벤트 핸들러가 누적되어 이벤트가 모두 실행되는 것을 확인할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const $test = document.getElementById("test");

const func1 = () => {
console.log("test1");
};
const func2 = () => {
console.log("test2");
};
const func3 = () => {
console.log("test3");
};

$test.addEventListener("click", func1);
$test.addEventListener("click", func2);
$test.addEventListener("click", func3);

이벤트 전파 정의

이벤트 핸들러 프로퍼티 방식과 달리 addEventListener 메서드 방식은 세 번째 매개변수로 버블링으로 작동될지, 캡쳐링으로 작동될지의 여부를 지정할 수 있습니다. 세 번째 매개변수가 true일 경우 캡쳐링을 사용하고false일 경우 버블링을 사용합니다.

따라서 이벤트 핸들러 프로퍼티 방식은 기존 이벤트 타입별 기본 적용된 전파 방식을 그대로 따라야 하는 반면 addEventListener 방식은 필요에 따라 전파 방식을 지정하여 유연한 코드 작성이 가능합니다.