자바스크립트 addeventlistener - jabaseukeulibteu addeventlistener

자바스크립트 addeventlistener - jabaseukeulibteu addeventlistener

이번 포스팅은 onclick과 addEventListener의 차이점에 대해 알아보겠습니다.

자바스크립트에서 클릭이벤트를 사용할 때 onclick과 addEventListener를 사용할 수 있습니다.

차이점을 알아보기 전에 다음과 같은 예시를 보고 가겠습니다.

<input type="button" value="클릭" class="btn">
var btn = document.querySelector('.btn');

btn.onclick = function() {
    console.log('100');
}

btn.onclick = function() {
    console.log('200');
}

btn.onclick = function() {
    console.log('300');
}

'클릭' 버튼을 누르면 콘솔 탭에 어떤 값이 출력이 될까요?

'300'만 출력이 됩니다.

자바스크립트 addeventlistener - jabaseukeulibteu addeventlistener

그렇다면 다음과 같은 코드의 결과값은 어떨까요?

var btn = document.querySelector('.btn');

btn.onclick = function() {
    console.log('100');
}

btn.onclick = function() {
    console.log('200');
}

btn.onclick = function() {
    console.log('300');
}

btn.addEventListener('click', function() {
    console.log('100');
});

btn.addEventListener('click', function() {
    console.log('200');
});


btn.addEventListener('click', function() {
    console.log('300');
});

결과는 '300', '100', '200', '300'이 출력됩니다.

자바스크립트 addeventlistener - jabaseukeulibteu addeventlistener

어떤 차이가 있는지 눈치채셨나요?

onclick과 addEventListener의 차이는 덮어쓰기 vs 누적입니다. 

onclick은 하나의 요소에 클릭 이벤트를 걸어줄 때마다 기존에 걸려있던 클릭 이벤트가 덮어쓰여집니다.

그렇기 때문에 처음 100, 200의 클릭 이벤트가 실행되지 않고 마지막 클릭 이벤트만 실행된 것입니다.

반면에 addEventListener는 하나의 요소에 클릭 이벤트를 누적해서 걸어줄 수 있습니다.그래서 모든 클릭 이벤트가 실행되어 100, 200, 300의 값을 출력한 것입니다.


그럼 둘 중에 무엇을 사용하는 것이 좋을까요?

제 생각은 케바케라고 생각합니다. 

가령 html을 작업하는 도중 급하게 어떤 버튼을 클릭했을 때 이벤트가 실행되는지 확인하고 싶다면 onclick을 사용하시면 됩니다.

<div onclick="location.href='www.naver.com'">
</div>

onclick은 html 태그에 인라인 방식으로 넣을 수 있습니다.

잠깐 테스트 용으로 사용하는 것이 좋으며 이를 남발한다면 코드가 많이 지저분할 것입니다.

addEventListener은 이벤트 캡쳐링과 버블링을 설정할 때 사용하면 좋습니다.

addEventListener('click', function() {}, false);

세 번째 인자에 이벤트 캡쳐링을 사용할지 안할지 판단을 하고 false, true로 설정해주시면 됩니다.

초기값은 false이기 때문에 이벤트 버블링이 기본적으로 설정되어 있습니다.

그리고 addEventListener는 인터넷익스플로러(IE) 8 버전 이하에서는 작동을 하지 않기 때문에 해당 버전을 고려해서 개발을 하신다면 attachEvent를 사용하셔야 합니다.

결론을 말하면 onclick보다 addEventListener를 사용함으로써 얻는 장점이 더 많다고 생각합니다.

우리가 사용하는 웹 사이트나 웹 애플리케이션에서는 수많은 이벤트가 발생합니다. 사용자가 마우스나 키보드로 일으킬 수 있는 이벤트도 있고, 브라우저 스스로도 웹페이지를 로딩하면서 여러 이벤트를 발생시킵니다.

이번 포스팅에서는 이렇게 웹에서 다양한 이유로 발생하는 이벤트를 처리하는 여러가지 방법에 대해서 알아보겠습니다.

HTML 이벤트 속성

먼저 가장 고전적이지만 사용하기 간단한 방법부터 알아볼까요?

HTML 요소(element)에서 발생하는 이벤트를 처리하는 가장 쉬운 방법은 HTML의 이벤트 속성을 활용하는 것입니다. on<이벤트 타입명> 형태를 갖는 이벤트 속성은 HTML의 모든 요소에 사용이 가능하며, 해당 타입의 이벤트 발생 시 실행할 자바스크립트 코드(이벤트 핸들러)를 속성 값으로 설정해줄 수 있습니다.

예를 들어, 다음 <button> 요소는 클릭했을 때, 브라우저 알람으로 클릭이라는 메세지가 뜰 것입니다.

<button onclick="alert(textContent)">클릭</button>

다른 예로, 다음 <input> 요소는 클릭했을 때, 브라우저 콘솔에 입력한 내용이 출력될 것입니다.

<input name="test" onchange="console.log(value)" />

여기서 자바스크립트 코드에 사용된 textContentvalue는 이벤트가 발생한 HTML 요소의 속성입니다. 이렇게 HTML의 이벤트 속성으로 사용된 자바스크립트 코드에서는 이벤트가 발생한 요소에 자연스럽게 접근할 수 있습니다.

이처럼 HTML 이벤트 속성은 간단한 코드를 실행하기에는 매우 간편하지만 이벤트 발생 시에 실행할 로직이 복잡한 경우에는 그닥 추천되지는 않습니다. 그리고 순수하게 HTML 기반인 이 방법에는 한가지 큰 제약 사항이 있는데 바로 이벤트 핸들러를 한 번 설정하면 제거하는 것이 어렵습니다. 다시말해, 이벤트 핸들러를 제거하려면 다음에 소개드릴 자바스크립트의 도움이 필요하게 됩니다.

JavaScript 이벤트 속성

HTML 요소에서 발생하는 이벤트를 처리하는 두 번째 방법은 자바스크립트의 DOM 노드의 이벤트 속성을 활용하는 것입니다.

우선 위에서 작성한 HTML 코드에서 이벤트 속성을 모두 제거하겠습니다.

그 다음, 자바스크립트로 <button> 요소를 선택 후 onclick 속성에 이벤트 핸들러 함수를 지정해주면 됩니다.

const buttonEl = document.querySelector("button");
buttonEl.onclick = function (event) {
  alert(this.textContent);
  // alert(event.target.textContent);
};

이벤트가 발생한 요소에 접근할 때는 this 키워드나 함수의 인자로 넘어온 event 매개 변수의 target 속성을 사용할 수 있습니다.

<input> 요소에도 마찬가지로 onchange 속성을 제거하겠습니다.

이번에는 코드가 좀 더 깔끔해 보이도록 function 키워드 대신에 => 기호를 사용하는 람다(lambda) 함수를 사용해보겠습니다.

const inputEl = document.querySelector("input");
inputEl.onchange = (event) => console.log(event.target.value);

이벤트 핸들러로 람다 함수를 사용할 때 주의할 점은 더 이상 this 키워드로 이벤트가 발생한 요소에 접근할 수 없다는 것입니다. 따라서 이벤트가 발생한 요소에 접근할 때는 반드시 event.target을 사용해야 합니다.

이벤트 핸들러를 제거할 때는 선택한 HTML 요소의 이벤트 속성을 null로 설정해주면 됩니다.

JavaScript 이벤트 함수

마지막으로 소개해드릴 방법은 자바스크립트의 DOM 노드를 대상으로 addEventListener() 함수를 호출하는 것입니다.

addEventListener() 함수는 첫 번째 인자로 이벤트 타입명을 두 번째 인자로 이벤트 핸들러를 받습니다.

따라서 위에서 onclick 속성에 지정했던 이벤트 핸들러 함수를 다음과 같이 click이라는 이벤트 타입명과 함께 addEventListener() 함수에 넘길 수가 있습니다.

const buttonEl = document.querySelector("button");
buttonEl.addEventListener("click", function (event) {
  alert(this.textContent);
});

물론 람다 함수로 이벤트 핸들러를 넘길 수도 있으며, 마찬가지로 이 때는 this 키워드로 이벤트가 발생한 요소에 접근할 수 없다는 점 주의해야 합니다.

const inputEl = document.querySelector("input");
inputEl.addEventListener("change", (event) => console.log(event.target.value));

addEventListener() 함수를 사용할 때 큰 이점은 바로 하나의 DOM 노드를 대상으로 이 함수를 여러번 호출할 수 있어서, 해당 HTML 요소에서 이벤트가 발생했을 때 여러 이벤트 핸들러를 실행할 수 있다는 것입니다.

예를 들어, <input> 요소에서 change 타입의 이벤트가 발생했을 때 이벤트 내용을 로깅하도록 logEvent라는 함수를 이벤트 핸들러로 추가해보겠습니다.

function logEvent(event) {
  console.log({
    type: event.type,
    name: event.target.name,
    value: event.target.value,
  });
}
inputEl.addEventListener("change", logEvent);

이제, <input> 요소에 안녕이라고 입력하면 아래와 같이 브라우저 콘솔에 이벤트 내용이 출력이 될 것입니다.

>> "안녕"
>> {
  "type": "change",
  "name": "test",
  "value": "안녕"
}

이벤트 핸들러를 제거할 때는 removeEventListener() 함수를 사용하여 이벤트 타입명과 이벤트 핸들러를 넘기면 됩니다.

inputEl.removeEventListener("change", logEvent);

마치면서

지금까지 웹페이지에서 발생하는 이벤트를 처리하는 대표적인 3가지 방법에 대해서 살펴보았습니다. 각 방법의 장단점을 간단하게 정리해보면,

  • HTML 이벤트 속성: 가장 고전적이지만 이벤트 핸들러가 간단할 경우 간편하게 게 쓸 수 있음. 이벤트 핸들러를 제거하기 어려움.
  • JavaScript 이벤트 속성: 위와 유사하나 자바스크립트를 사용하며 쉽게 이벤트 핸들러를 제거할 수 있음.
  • JavaScript 이벤트 함수: 여러 이벤트 핸들러를 유연하게 추가하거나 제거할 수 있음. 사용법이 상대적으로 어려움.

개인적으로는 저는 가장 강력한 마지막 방법을 추천드리고 싶지만 첫번째나 두번째 방법도 잘 숙지해두시면 기존에 작성된 코드를 읽을 때 도움이 되실 겁니다. 이벤트 처리는 어떤 프레임워크로 웹 개발을 하든 반드시 알아야 할 부분이오니 이번 기회에 잘 정리해두셨으면 좋겠습니다.