이벤트 버블링, 캡쳐링, 이벤트 위임

오늘도 삽질중·2023년 2월 17일
0

Javascript

목록 보기
5/5
post-thumbnail

이전 프로젝트에서 버튼을 클릭하면 원치 않는 기능이 작동되었던 기억이 있다.그 때 일어났던 현상이 바로 '이벤트 버블링'이라는 것이었는데, 결국 해결은 하긴 했지만 시간이 지나니 뭐가 뭐였는지 기억이 흐릿해져갔다.
면접 질문으로도 자주 나온다하니

이벤트의 현상 대해 정리해보자~

✅ 이벤트 버블링

이벤트 버블링이란, 상위 엘리먼트와 하위 엘리먼트가 있을때 하위 엘리먼트 이벤트를 클릭하면 클릭한 하위 엘리먼트에서부터 상위 엘리먼트까지 이벤트가 전달되는 방식을 말한다.

  • 예를 들어보자.

<D onClick={() => console.log('D')}> // 검정박스
     <U onClick={() => console.log('U')}> // 초록박스
        <L onClick={() => console.log('L')}>예시</L> // 빨간박스
      </U>
</D>

여기서 가장 하위 엘리먼트인 <L>을 클릭하게되면 어떻게 될까?

<L> 태그를 눌렀을 시, L-U-D 차례로 콘솔이 찍히는것을 볼 수 있다. 이게 바로 버블링이다

좀 더 버블링 예시를 보자

<U>를 눌렀을 시, U-D

<D>를 눌렀을 시, D

이벤트 버블링 동작
이벤트 버블링
<L> 태그를 눌렀을 시, L-U-D 차례로 콘솔이 찍히는 부분이 잘린 것 같다. gif는 그냥 참고로 봐주세욤~

다음은 이벤트 캡쳐링에 대해 알아보자.

✅ 이벤트 캡쳐링

이벤트 캡쳐링이란, 상위, 중간, 하위 엘리먼트가 있을 때 (중간 엘리먼트에 캡쳐링 옵션을 준 상태), 하위 엘리먼트 이벤트를 클릭하면 그 위의 상위 엘리먼트들 중 캡쳐링이 있는 엘리먼트를 찾아 이벤트를 발생시키고, 그 다음 클릭한 하위 엘리먼트부터 상위 엘리먼트까지 이벤트가 전달되는 방식을 말한다.

예를 들어보자.

<C onClick={() => console.log('콘')}>
<D onClick={() => console.log('D')}>
      <U onClickCapture={() => console.log('U')}>
        <L onClick={() => console.log('L')}>예시</L>
      </U>
    </D>
</C>

이벤트 캡쳐링을 발생시키기 위해서는 옵션을 줘야 한다.
(이벤트는 기본적인 동작방식이'이벤트 버블링'이기 때문에 자바스크립트 기준 addEventListener()
마지막 인자로 {capture: true} 를 전달해주면 캡쳐링으로 바꿔줄 수 있다.)
나는 jsx로 예를 들었기 때문에 onClickCapture이벤트를 전달해 주었다.

하위 엘리먼트 을 누르면 어떻게 될까?


U-L-D-콘

하위엘리먼트 <L>을 눌렀을 시, 상위 엘리먼트들 중 캡쳐링이 있는 엘리먼트를 찾아 먼저 이벤트 발생시키고(U), 클릭했던 하위 엘리먼트(L) ~ 상위 엘리먼트 까지(D-콘) 이벤트가 버블링으로 실행되는걸 볼 수 있다.

이벤트 캡쳐링

만약 클릭한 상위 엘리먼트들 중 캡쳐링이 없다면 무난히 버블링으로 이벤트가 발생하는것 또한 gif를 통해 볼 수 있다.

✅ 이벤트 위임 (event delegation)

버블링과, 캡쳐링을 이해했다면 이벤트 위임을 이해하는건 쉽다

이벤트 위임이란, 상위 엘리먼트와 하위 엘리먼트들이 있을 때 하위 엘리먼트들에 각각 이벤트 핸들러를 달지 않고 상위 엘리먼트에 이벤트 핸들러를 달아 하위 엘리먼트들을 제어하는 방식을 말한다.

이번엔 자바스크립트 코드 예시다.

<ul onclick="alert("주의하세용")">
  <li>첫번째</li>
  <li>두번째</li>
  <li>세번째</li>
</ul>

<li> 태그 어느것을 클릭해도 <ul>의 이벤트가 발생하는걸 볼 수 있다.

이벤트 위임을 사용해서 장점은 무엇일까? 👍

이벤트 위임 장점 👍

  • 코드가 깔끔해진다., 가독성이 좋다 (onclick="alert("주의하세용")"의 이벤트가 <li>각각의 태그에 달려있다 생각해보면 이벤트 위임을 사용해서 코드를 작성하는것이 얼마나 깔끔한지 알 수 있을거다)
  • 동적으로 엘리먼트를 추가할 때마다 핸들러를 고려할 필요가 없다. (<li>네번째</li>를 추가하고 싶으면 이벤트를 뭐 줄 지 생각을 굳이 하지 않고도 추가하면 된다)
  • 메모리에 있게되는 이벤트 핸들러가 적어지기 때문에 퍼포먼스 측면에서 이점이 있다.

하지만 무조건 적으로 이벤트 위임을 사용하게 되면 내가 프로젝트에서 겪었던 오류(해당 이벤트를 클릭했는데, 엉뚱한 이벤트가 발생해서 도대체 이게 무슨일이지?했음)를 찾아내기까지 꽤 오랜 시간을 겪고 혼란스러울 수 있기 때문에 상황에 맞게 잘 사용하는게 중요한것 같다.

✅ event.stopPropagation()

마무리로 '이벤트 버블링,캡쳐링을 신경쓰고 싶지 않다' 혹은 '원치 않은 이벤트 버블링,캡쳐링이 발생했는데 이를 멈추고 싶다'하면 event.stopPropagation() 을 사용하면 된다!

// 이벤트 캡쳐 예제코드, (자바스크립트로)
divs.forEach(function(div) {
	div.addEventListener('click', logEvent, {
		capture: true // default 값은 false입니다.(버블링이 디폴트)
	});
});

function logEvent(event) {
	event.stopPropagation();
	console.log(event.currentTarget.className); // one
}

참고자료

profile
의미없는 삽질은 없다1

0개의 댓글