[JavaScript] 이벤트 버블링 & 이벤트 캡쳐링

D uuu·2023년 12월 26일
0

JavaScript

목록 보기
7/8

이벤트 동작 방식

1. 이벤트 발생 : 이벤트는 사용자가 마우스를 클릭한다던가, 키보드를 입력한다던가 하는 등 상호작용에서 발생합니다.

2. 이벤트 리스너 등록 : 개발자는 위와 같이 특정 이벤트가 발생했을때 실행할 코드를 정의하는 이벤트 리스너를 등록합니다.

3. 이벤트 전파 : 이벤트 전파는 HTML 문서의 DOM 트리 구조를 따라 이벤트가 전달 되는 과정을 의미합니다. 이벤트가 발생하면 이벤트가 발생한 요소에서 시작해서 자신의 상위 요소로 전파되어 가는 방식을 이벤트 버블링이라고 하며, 반대로 이벤트가 최상위 요소에서 시작해서 실제 이벤트가 발생한 요소로 전파되어 가는 방식을 이벤트 캡쳐링이라고 합니다.

4. 이벤트 핸들러 실행 : 등록된 이벤트 리스너는 해당 이벤트가 발생하면 실행 됩니다. 이벤트 객체(event object)는 이벤트에 대한 정보를 포함하고 있어서 이를 활용하여 이벤트 동작을 조작할 수 있습니다.

5. 기본 동작 제어 : 일부 이벤트는 기본 동작을 가지고 있습니다. 예를들어 <a> 태그는 클릭하면 페이지를 이동하게 되는데 이러한 기본 동작을 막고자 할때 preventDefault 메서드를 이용할 수 있으며, 이벤트의 전파를 막고 싶을때는 stopPropagation 메소드를 사용해 이벤트 버블링, 이벤트 캡쳐링과 같은 전파를 막을 수 있습니다.

이벤트 버블링 - Event Bubbling

이벤트 버블링은 특정 화면 요소에서 이벤트가 발생했을 때 해당 이벤트가 더 상위의 화면 요소들로 전달되어 가는 특성을 의미합니다. 아래 그림과 같이 맨아래 하위 요소 div 에서 이벤트가 발생하면 이벤트가 상위 요소들을 타고 올라가 body, 즉 최상위 요소까지 전달 되어 갑니다.

마치 거품(bubbling) 이 보글보글 끓어 올라가는 모습과 닮았다 하여 이벤트 버블링이라고 이름이 붙여졌다고 합니다.

✨브라우저의 이벤트는 기본적으로 버블링 방식으로 이벤트가 전파됩니다. 자바스크립트 addEventListener() 함수로 요소의 이벤트를 등록하면 기본적으로 버블링 전파 방식으로 이벤트가 흐르게 되어, 만일 자식 요소에 이벤트가 발생하면 부모 요소도 버블링 통해 이벤트가 전파되어 리스너가 호출되게 됩니다.

상위의 화면 요소란? HTML 요소는 기본적으로 트리 구조를 갖습니다. 여기서 트리 구조는 자신 보다 한 단계 위에 있는 요소를 상위 요소라고 하며 body 태그를 최상위 요소라고 생각합니다.

<body>
    <div class="div1">1번
      <div class="div2">2번
        <div class="div3">3번</div>
      </div>
    </div>
  </body>
const divs = document.querySelectorAll("div");

const clickEvent = (e) => {
  console.log(e.currentTarget.className);
};

divs.forEach((div) => {
  div.addEventListener("click", clickEvent);
});

3번을 클릭 했는데, 콘솔을 보면 div3, div2, div1 이 모두 찍혀있다.
2번을 클릭하면, 콘솔에 div2, div1 이 찍힌다.

이벤트 위임

이벤트 버블링 특징을 이용해서 아래와 같이 구현할 수 있습니다.
아래와 같이 여러개의 리스트가 있을때, 몇번째 아이템을 클릭하든 이벤트를 발생시키고 싶다고 합시다. 만일 이벤트 전파 개념이 없다면, <li> 요소 마다 일일이 이벤트를 등록해야 할지도 모릅니다. 하지만 이벤트 버블링 특성을 이용해 우리는 부모 요소인 <ul> 요소에만 이벤트를 등록해 몇번째의 li 요소를 클릭하든 부모 요소로 이벤트가 전파되기 때문에 원하는바를 간단하게 구현할 수 있습니다.

const clickEvent = (e) => {
	console.log(e.currentTaget.id)
}

<ul id="item-list" onClick={clickEvent}>
<li id="item1">Item1</li>
<li id="item2">Item2</li>
<li id="item3">Item3</li>
<li id="item4">Item4</li>
<li id="item5">Item5</li>
</ul>

이벤트 캡쳐링

이벤트 캡쳐링은 한 요소에 이벤트가 발생하면, 그 요소의 자손 요소의 이벤트도 같이 발생되는 이벤트 전파를 말합니다. 이벤트 버블링의 반대 개념이라고 생각하시면 됩니다. 실무에서는 자주 쓰이지는 않지만 가끔 유용한 경유가 있습니다.

브라우저의 이벤트 전파 방식은 버블링이 기본값이기 때문에 캡쳐링으로 설정하려면 별도의 옵션을 함수에 주어야 합니다.

addEventListener() 함수의 3번째 매개변수로 true 값을 주면 이 이벤트 타겟은 캡쳐링을 통해 이벤트를 전파받아 호출되게 됩니다.

  <body>
    <div class="div1">
      1번
      <div class="div2">
        2번
        <div class="div3">3번</div>
      </div>
    </div>
  </body>
const divs = document.querySelectorAll("div");

const clickEvent = (e) => {
  console.log(e.currentTarget.className);
};

divs.forEach((div) => {
  div.addEventListener("click", clickEvent, { capture: true });
});

3번을 클릭했는데 콘솔에는 상위 요소에서 아래로 이벤트가 전파되기 때문에 div1, div2, div3 순서로 찍히게 됩니다.
2번을 클릭하면, div1, div2 순서로 찍힙니다.

이벤트 캡쳐링은 어떻게 활용할까?

이벤트 위임에서 살펴봤듯이 이벤트 버블링은 자식 요소에 일일이 이벤트를 등록하지 않고, 부모 요소에만 이벤트를 등록하는 방법으로 유연하게 코드를 작성할 수 있습니다.

그렇다면 이벤트 캡쳐링은 주로 어떻게 쓰일까요?
이벤트 캡쳐링은 보통 애플리케이션에서 사용자의 상호작용을 기록하거나 모니터링하는데 사용 됩니다. 예를들어 온라인 쇼핑앱에서 이벤트 캡쳐링은 아래와 같이 활용 됩니다.

  • 사용자 행동 분석 : 사용자가 상품을 클릭하거나 장바구니에 넣는 등의 행동을 추적하여 어떤 상품이 관심을 끌고 있는지, 어떤 상품이 장바구니에 담기는지 등을 파악할 수 있습니다.

  • 결제 과정 분석 : 결제 단계에서 사용자가 어떤 이유로 결제를 중단했는지, 어떤 결제 방식을 선호하는지 등을 파악해서 사용자 경험을 개선할 수 있습니다.

  • 에러 및 버그 추적 : 어떤 상황에서 앱이 오류를 발생시키는지, 어떤 조건에서 앱이 다운되는지 등을 기록하여 문제를 해결하고 사용자 경험을 향상시킬 수 있습니다.

  • A/B 테스트 : 서로 다른 기능이나 디자인을 가진 두가지 버전을 사용자들에게 제공하여 어떤 버전이 더 효과적인지 알아보는데 사용될 수 있습니다.

이벤트 전파 방지 방법

stopPropagationpreventDefault 는 모두 JavaScript에서 이벤트 처리에 사용됩니다.

  • stopPropagation( ) 메소드를 호출하면 버블링이나 캡처링 단계에서 이벤트 전파를 막을 수 있습니다.

  • 특정 요소에서 발생한 이벤트가 해당 요소의 부모나 자식 요소로 계속 전달되는 것을 막아, 다른 요소들이 해당 이벤트를 감지하지 못하도록 합니다.

  • 아래 처럼 child 이벤트 리스너에 stopPropagation 메소드를 호출하면 상위 (부모) 로 이벤트가 전파되는 걸 막아줍니다.

child.addEvnetListener('click', (e) => {
	e.stopPropagation()
    ////
}
  • preventDefault( ) 는 정말 자주 쓰이는 메소드라 익숙한데 정작 잘 모르고 쓰는 경우가 많은 것 같습니다. 일반적으로 특정 이벤트의 기본 동작을 취소 합니다.

  • 예를들어 <a> 태그를 클릭했을때 새로운 페이지로 이동하는 것을 막아주거나, <form> 태그를 사용할 경우 submit 이벤트가 발생했을때 페이지 새로고침을 막아줍니다.

  • 이벤트의 기본 동작을 막아 사용자 정의 동작을 수행할 수 있게 해줍니다.

간단히 말하자면,
prevnetDefault( ) 는 이벤트의 기본 동작을 막아주고,
stopPropagation( ) 는 부모 요소 or 자식 요소에게 이벤트가 전파되는 걸 막아줍니다.
※ 종종 두 메소드를 함께 사용하여 이벤트를 완전히 제어하기도 합니다.





도움 받은 곳
https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-%EB%B2%84%EB%B8%94%EB%A7%81-%EC%BA%A1%EC%B3%90%EB%A7%81

https://joshua1988.github.io/web-development/javascript/event-propagation-delegation/

profile
배우고 느낀 걸 기록하는 공간

0개의 댓글