onclick vs addEventListener('click')

10859 단어 JavaScriptJavaScript

개요

const elem = document.querySelector('.testElem')

elem.addEventListener('click',function(){
	console.log('hello!');
})
 // #1
.....

const testTag = document.createElement('button')
testTag.onclick=function(){
	console.log('hello!');
}
 // #2

<button class='testElem' onclick='(e) => {console.log('hello!')}'

 // #3

여지껏 텍스트로 포스팅을 시작했던 것 같은데

뜬금없이 코드로 시작해보았습니다.

이 글을 쓰는 이유는,

'댓글 달기'와 같은 element 추가가 필요한 경우에
해당 댓글 element에 event가 붙어있어야하는 경우
위의 3가지 방법 중 어떤 것이 효율적이고, 지향되어야하는가?

에 대한 물음표가 있었습니다.

사실 직관적이고 편해서 element.onclick = ~ 방식으로 쓰곤 했는데

많은 문서들을 찾아보고 난 뒤, 생각이 바뀐 부분이 있어 정리합니다.

우선 서두에 참고한 링크부터 올립니다.

참고 링크
1. https://www.geeksforgeeks.org/difference-between-addeventlistener-and-onclick-in-javascript/
// 단순한 차이점에 대한 설명
2. https://newbedev.com/addeventlistener-vs-onclick
// 'Why?'에 시점이 있는 설명

Element에 요소를 적용하는 방법

편의상 후술할 코드들의 태그는 self closure를 적용합니다.

Inline event

<button onclick='alert('안녕!')'/>

간단히 html 페이지 내에 사용하는 방식입니다.

아마 가장 처음 학습할 때 제일 먼저 맞닥뜨리는 것이 아닐까 생각합니다

onclick attribute

const elem = document.createElement('button')
elem.onclick = function(){
	alert('안녕!');
}
parentNode.appendChild(elem);

JS를 이용한다면 Inline event와 똑같은 동작을 만들 수 있습니다.

방법은 다르지만 결과적으로 똑같습니다.

addEventListener

const elem = document.querySelector('.testElem');
elem.addEventListener('click',function(){
	alert('안녕!');
})

html에 있는 요소를 불러오고 해당 요소에 이벤트를 등록하는 방식입니다.

동작은 똑같지만 html 상에서 보이지 않으며 방법 또한 확연히 다릅니다.

What is difference?

html 상으로 보이느냐? 보이지 않느냐?

바로 위에 서술했듯이 Inline event를 적용한다면

개발자 도구를 열어서 어떤 동작이 적용됐을지 알 수 있습니다.

하지만 JS에서 선언한다면 보이는 현상을 막을 수 있습니다.

Duplicate?

elem.onclick = function(){
	console.log('안녕! 첫 번째 함수야!")
}

elem.onclick = function(){
	console.log('안녕! 두 번째 함수야!")
}

위처럼 동일한 Inline event를 등록하게 되면

마지막에 등록된 이벤트가 실행됩니다.

즉, 하나의 이벤트에 여러가지 작업을 동시에 붙일 수 없습니다.

하지만 addEventListener의 경우

elem.addEventListener('click',function(){
	console.log('안녕! 첫 번째 함수야!")
}

elem.addEventListener('click',function(){
	console.log("안녕! 두 번째 함수야!")
}

이 때 두 console.log가 모두 실행됩니다.

그러므로 여기서 onclick은 어떠한 동작 '한가지'만 필요하다면 괜찮지만

여러 상호작용이 필요할 수 있다! 라고 했을 때는

addEventListener가 필요하다고 생각됩니다.

Event Capturing

elem.addEventListener('click',function(){},false)

addEventListener는 세 번째 인자로 Event capturing을 제어하는

boolean 인자가 있고, 기본 값은 false입니다.

예를 들어...

<div>
 <p>
  <button>
 </p>
</div>

위와 같은 형태에 button 태그에 true 값이 정해져 있다면

div -> p -> button 순서로 캡쳐링이 진행된 뒤

button -> p -> div 순서로 버블링이 이어집니다.

false일 때는 캡쳐링이 설정되지 않았으므로

button -> p -> div 순서로 버블링만 발생합니다.

What is Bubbling, Capturing?

Bubbling : Event가 상위 요소로 전파됩니다.
 -> 아래에서 위로!
Capturing : Event가 하위 요소로 전파됩니다.
 -> 위에서 아래로!

Difference Summary

Why addEventListener?

제가 내린 결론은 아래와 같습니다.

onclick보다 addEventListener를 가까이하자!

Reason 1 : 여러가지 Event들

앞서 서술했듯이 onclick은 한 개의 작업만 등록할 수 있습니다.

하지만 addEventListener는 하나의 동작에 여러가지 작업을 부여할 수 있습니다.

Reason 2 : html stress

<button onclick=''/>
<button onclick=''/>
<button onclick=''/>
<button onclick=''/>
<button onclick=''/>
<button onclick=''/>

예를 들어 위와 같이 버튼 하나하나에 click 이벤트가 필요할 때

html에 하나하나 작성을 해버린다면...

처음 로드될 때의 시간이 길어질뿐만 아니라 가독성이 좋지 않습니다.

Reason 3 : XSS Risks

Cross Site Scripting
 :: 페이지에 스크립트를 삽입해 공격하는 기법
 :: 보여지는 태그를 확인해 작업을 변조할 수 있고
 :: 경우에 따라 악의적인 URL을 삽입시켜 악성 코드를 다운받게 하거나
 :: 쿠키, 세션 정보 등을 갈취할 수 있고
 :: 서버의 권한을 취득할 수도 있습니다.

해킹 기법에는 XSS, 크로스 사이트 스크립팅이라는 기법이 있고

그 특징은 위와 같습니다.

예를 들어 button onclick에 세션을 탈취하여 전송하는 로직을 끼워놓는다면,
사용자가 버튼을 클릭했을 때 사용자의 정보가 통째로 보내질 겁니다.

물론 이러한 공격은 서버 단에서 처리하는 것이 맞긴 하지만,

기본적으로 화면 단의 구성을 통해 예방하는 것 또한 맞겠지요.

그러한 부분에서 쉽게 현재 적용된 스크립트를 볼 수 없게끔

Inline event handler를 지양해야된다고 생각했습니다.

Simple solution

function XSSCheck(str, level) {
    if (level == undefined || level == 0) {
        str = str.replace(/\<|\>|\"|\'|\%|\;|\(|\)|\&|\+|\-/g,"");
    } else if (level != undefined && level == 1) {
        str = str.replace(/\</g, "&lt;");
        str = str.replace(/\>/g, "&gt;");
    }
    return str;
}

JS에서 방어하는 방법은 대표적으로 2가지 정도가 있는데,

첫 번째는 위의 정규식 치환 방법으로 input값을 필터링하는 것이 있고

두 번째는 보안 전문 업체를 사용하거나 라이브러리를 가져오는 것이 있습니다.

참고 링크 : https://doctorson0309.tistory.com/601

Performance?

성능은 브라우저에 따라 다르게 측정된다는 이야기가 있습니다.

참고 링크 : https://stackoverflow.com/questions/26008243/is-it-more-efficient-to-use-addeventlistener-or-onclick-for-performance

예를 들어 크롬에서는 addEventListener가 더 빨랐지만

FireFox에서는 onClick이 더 빨랐다는 의견이 있습니다.

따라서 성능상의 비교는 어려운 것 같고, 그 내부의 작업이 얼마나 Heavy한지에 따라 달라질 것 같습니다.


마무리

Inline event handler는 작성이 간편하고 코드의 줄이 많이 줄어듭니다.

하지만 여러 실습을 해보면서 느낀 것 중 하나는

웹에서 발생하는 이벤트들은 단순한 하나의 익명 함수로만 끝나지 않습니다.

예를 들면 서버에 DB를 요청해 특정 필터링된 데이터만 가져온다던가... 하는
Complex한 동작들이 있습니다.

더불어 Angular나 React 같은 경우

<button onclick={doSomething()}/>

인라인 이벤트처럼 보이지만 백그라운드에서 더 복잡한 코드로 변환되어,

어쨌든 html이나 Vanilla JS에서 일컫는 인라인 이벤트처럼 작동하지 않는다고 합니다.

그래서.. 사실 addEventListener를 사용할 일은 딱히 있진 않겠지만

Inline event handler의 사용을 지양해야겠다는 생각을 하게 되었습니다.

좋은 웹페이지 즐겨찾기