[JS] click Event 와 버블링 활용 그리고 Memory 절약

Castle_Junny·2023년 9월 10일
0

자바스크립트

목록 보기
2/2
post-thumbnail

Front 개발을 하다보면 click,keyboard 등등의 event를 숙명적으로 사용하게 된다.
근데 이것들을 사용하다보면 이벤트가 두번 씩 실행되거나, 버블링 같은 다양한 문제를 직면하게 된다.

그리고 이벤트를 발생시키는 방법이 addEventListner, onclick 두 가지가 있고 다른 글을 찾아봤을 때 onclick을 사용할 땐 버블링을 막지 못하니 addEventListenr를 사용하는게 좋다는 글들이 주로 보였다. 그래서 나도 계속 그렇게 사용을 해왔었다.

근데 최근에onclick도 동일하게 막을 수 있고, Event를 생성할 때 버블링을 잘 활용하면 Memory의 사용을 줄일 수 있겠다는 생각이 들어서 테스트를 진행해보았다.

개발을 하면서 마주한 여러가지 상황에 대해서 서술을 해보려고 한다.

Event 생성은 누구나 알듯이 addEventListener , onclick 등이 있다.
그리고 Event를 다루다보면 필연적으로 버블링(Bubbling) 현상과 태그의 기본 실행 같은 걸 마주한다.

1. 버블링(Bubbling)

버블링은 쉽게 이야기하면 옛날 오락실게임 '보글보글'을 생각하면 된다.

하나의 Tag에서 이벤트가 발생하면 거품처럼 하늘로 올라갈때까지 계~속 올라가는현상이다.

아래 코드펜의 코드를 보면 모든 tagclick Event (addEventListener) 를 걸어두었다.
제일 아래의 button div를 눌리면 거품의 시작은 button이고
nav에서 클릭을 하면 nav에서 부터 거품이 시작된다.

왜냐하면 button를 눌렀다는것으느 btnWrap을 눌린 것이기도하고 container를 눌린것이기도 하고
html을 눌린 것이기도 하고 window를 눌린것이기도 하기 때문이다.

비유해서 설명하면 철수네 가족에는 아들 훈이가 있는데, 길가다가 훈이를 건드리면 철수네 가족 모두가 발작을 한다는 거..?

1.2 버블링 방지

그리고 이런 버블링을 막을 수 있는 방법은 stopPropagation()가 있다.
Propagation의 사전적 의미는 번식, 전파를 뜻한다. 그러니까 전파는 멈추겠다고 선언하는 것.

1.2.1 addEventListener


element.addEventListener('click', (event) => event.stopPropagation());

1.2.2 onclick

onclick의 경우 인라인 태그 내에서 혹은 동적으로 사용 될 수 있다.

  • 인라인 태그 내에서 사용 시

event.stopPropagation(); 를 해준 다음 실행할 function을 호출해주면 된다.

<div onclick="event.stopPropagation(); clickEvent()">button 1</div>
  • 동적으로 사용 시

해당 element를 불러다가 onclick 시 이벤트를 정의해주면 된다.


<div id="test">test<div>

<script>

  test.onclick = (event) => {
	  event.stopPropagation();
  }
  
</sctript>
  

2.캡처링(capturing)

캡처링의 사전적의미를 보면 사로잡다 라는 뜻을 갖고 있다.
버블링은 이벤트가 안에서 바깥으로 올라간 것이라면,
캡처링은 반대로 바깥에서 구석으로 몰아붙이는 것 위에서 아래로 내리갈굼 하는 거라고 생각하면 될거 같다.

( '사로잡는다' 라고 하면 나는 동물들이 사냥할 때 포위망을 좁혀가는 형태의 이미지가 떠오른다.)

캡처링을 아직 실무에서 사용할 일이 없어서 사용해 본적은 없지만 캡처링을 실행시키려면
addEventListener세번째 인자값(options) 을 건드려야한다.

해당 options에 대해서 자세히 알고 싶으면 MDN 홈페이지를 들어가면 자세히 볼 수 있다. (링크)

아무튼 캡처링을 실행하는 방법은 addEventListener('click', function , {captue : true} 로 해주면 된다.

3. Tag의 기본기능 막기

기존 기능 막기하는것은 뭐라고 해야할지 몰라서 내가 그냥 서술한 거다.

만약 <a> 에 네이버를 연결하는 링크를 걸어뒀다고 했을 때 해당 태그를 선택하면 페이지가 전환된다. 왜냐면 그게 <a> 태그의 기능이니까!

<a class="btn" href="https://www.naver.com">naver</a>

그런 기본 동작을 막을 수 있는게 preventDefault() 이다.
그럼 이걸 어떻게 사용할 수 있는지 다양한 예시를 아래를 코드를 통해 확인할 수 있다.

addEventListener 를 사용할 경우 evnet.preventDefault()를 해주면 되고

onclick 또한 동일하지만 Inline에서 event 값을 넘겨줘야 하는 방법 하나와 return false 를 해주는 방법 두가지가 있다는 점에서 새롭게 다가왔다.

4. 메모리 절약

뭐 이런식으로 실무를 하면서 Event를 다룰 때 겪을 수 있는 상황에 대비하는 것에 대해서 알아봤다.

그리고 버블링을 이용하면 메모리를 줄일 수 있겠다는 생각이 들어서 메모리 측면에서 어떤 차이가 있는지 확인해 보았다.

4.1 개선 전

<div class="container">
    <div class="btn">버튼 1</div>
    <div class="btn">버튼 2</div>
    <div class="btn">버튼 3</div>
    <div class="btn">버튼 4</div>
    <div class="btn">버튼 5</div>
    <div class="btn">버튼 6</div>
    <div class="btn">버튼 7</div>
    <div class="btn">버튼 8</div>
    <div class="btn">버튼 9</div>
</div>

위 코드와 같은 구조가 있다.
div모두 총 9개의 EventListener를 달았다. 그리고 크롬의 개발자 도구에서 Memory 사용량을 측정해 보았다.

위 테스트는 새로고침을 열번 했을 때 쌓이는 Listener 의 총 갯수를 보여준다.

총갯수가 108개로 새로고침을 할 때마다 EventListener가 쌓이는 것을 볼 수 있다.

4.2 개선 후

그렇다면 위에서 확인했던 버블링(bubbling)을 활용하여 .containerEventListener를 달면 어떻게 될까?

동작은 역시 동일하게 하는 것을 확인 할 수 있다.

그렇다면 메모리 사용량은 어떨까? 동일하게 새로고침을 열번 반복해 보았다.

결과는 최대 11개EventListener를 생성한 것을 볼 수 있다. 그러니 개선 전 코드보다 갯수를 10배 가량 줄일수 있었던 것이다.

자바스크립트도 내부적으로 가비지 컬렉션(Garbage Collection)을 통해 내부적으로 사용하지 않는 메모리를 제거한다고 알고는 있지만 그래도 개발자가 조절할 수 있는 선에서 메모리를 줄인다면 품질을 향상시키는데 많은 도움이 될 거 같다.

-

아무튼 이렇게 하는게 이벤트 위임 (event delegation)인데 캡처링과 버블링을 활용하여 구현할 수 있다.

이렇게 동작이 되는 것은 event.target 이 내가 선택한 target 이기 때문에 해당 요소에 대해 이벤트를 실행시킬 수 있는 것이다.

5. 결론

자바스크립트의 세상은 정말 다양하고 넓은 것 같다. 알면 알수록 새롭고 공부할 게 너무 많다. 언제 자바스크립트 고수가 될지 모르겠지만 하나씩 하나씩 해쳐나가보자!

-

[참고자료]
https://www.youtube.com/watch?v=OmrxrHSrS2Y
https://ko.javascript.info/

0개의 댓글