본문 바로가기
Javascript

[JS] Event Bubbling and Event Capturing

by SeanK 2021. 12. 5.

 

 

React를 공부하다가 event.stopPropagation() 메소드를 보았다. 

 

도대체 event.stopPropagation() 메소드가 왜 필요한지 조사를 해보니... 

 

자바스크립트가 이벤트를 실행 할 때 event 버블링 현상이 발생하기 때문에 event bubbling 현상을

 

막기 위해 해당 메소드가 필요하다고 한다. 

 

그렇다면 이벤트 버블링이란 무엇이고 왜 발생하는 것일까?

 

아래 블로그에 관련된 내용이 자세히 설명되어 있어 번역해 옮겨본다. 

 

출처: https://vsvaibhav2016.medium.com/event-bubbling-and-event-capturing-in-javascript-6ff38bec30e

 

Event Bubbling and Event Capturing in JavaScript

Event Bubbling and Event Capturing is the most used terminology in JavaScript at the time of event flow. In the JavaScript, Event Flow…

vsvaibhav2016.medium.com

 

Event Bubbling and Event Capturing in Javascript

 

자바스크립트에서 이벤트 플로우와 관련해서 Event Bubbling과 Event Capturing은 가장 많이 사용되는 용어 중 하나다. 자바스크립트에서, event flow 과정은 아래 세 가지 개념으로 구성된다:

 

  1. Event Capturing
  2. Event Target
  3. Event Bubbling

Events:

Events는 HTML 웹페이지와 자바스크립트의 상효작용을 책임진다. 일반적인 event의 정의는 누군가에 의해 발생할 수 있는 어떠한 행위라고 내리는데, 웹 개발에서의 정의 또한 같다. Events는 오로지 특정한 이벤트가 발생되었을 때에만 작동하는 Listeners에 의해 구독(subscribe)될 수 있다. 

 

Event Flow:

이벤트 플로우는 웹 페이지 상에서 어떤 이벤트가 반환되는 순서를 말한다. 만약 당신이 다른 엘리먼트 내에 소속된 div나 button 엘리먼트를 클릭한다면, 클릭이 타겟 엘리먼트에서 수행되기 이전에 클릭 이벤트는 global window object를 시작으로 위에서 아래로 각각의 부모 엘리먼트에서 우선 작동된다. 기본적으로 모든 HTML엘리먼트는 window object의 자식 엘리먼트다. 

 

History of Event Flow:

4세대 웹브라우저 전쟁에서, 주요 브라우저 커뮤니티인 Internet Explorer 4와 Netscape Communicator4는 이벤트 플로우를 해결한 방안을 위해 서로 모였다. 두 개발팀은 어떤 이벤트 플로우가 더 적절한가에 대한 논의를 나누었는데, 두 가지 방안이 있었다. Top to Bottom(Event Capturing)과 Bottom to Top(Event Bubbling). 하지만 불행히도, 두 팀은 서로 다른 접근법을 취했다. Internet Explorer 4는 이벤트 버블링 접근을, Netscape communicator 4는 이벤트 캡쳐링 접근을 선택했다.  

 

Event Bubbling:

Event Bubbling은 엘리먼트의 가장 아래 혹은 타겟 엘리먼트에서 그 부모로, 그리고 모든 조상 엘리먼트로 점차 작동하는 Bottom to top 이벤트를 뜻한다. 현재로서는 모든 모던 웹브라우저는 기본 이벤트 플로우 값으로 event bubbling 방식을 지원한다.

 

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Event Bubbling</title>
</head>
<body>
  <div id="parent">
    <button id="child">Child</button>
  </div>
  
  <script>
    var parent = document.querySelector('#parent');
    <!-- Add click event on parent div -->
      parent.addEventListener('click', function(){
        console.log("Parent clicked");
      });

    var child = document.querySelector('#child');
    <!-- Add click event on child button -->
      child.addEventListener('click', function(){
        console.log("Child clicked");
      });
  </script>
</body>
</html>

만약 위의 코드에서 button을 클릭하면, 이벤트는 안의 이벤트 타겟(id가 child인 버튼)에서 Document로 넘겨진다. Click 이벤트는 아래와 같은 순서로 넘겨진다. 

 

  1. <button>
  2. <div>
  3. <body>
  4. <html>
  5. document

 

Stop Event Bubbling:

 만약 이벤트 버블링을 멈추고 싶다면, event.stopPropagation()메소드를 통해 멈출 수 있다. 만약 이벤트 타겟에서 DOM 상위 엘리먼트로 흐르는 것을 멈추고 싶다면, event.stopPropagation()메소드는 아래에서 위로 여행하는 event를 멈출 수 있다. 

 

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Event Bubbling</title>
</head>
<body>
  <div id="parent">
    <button id="child" onclick="event.stopPropagation()">Child</button>
  </div>
  
  <script>
    var parent = document.querySelector('#parent');
    <!-- Add click event on parent div -->
      parent.addEventListener('click', function(){
        console.log("Parent clicked");
      });
    var child = document.querySelector('#child');
    <!-- Add click event on child button -->
      child.addEventListener('click', function(){
        console.log("Child clicked");
      });
  </script>
</body>
</html>

 

Event Capturing:

Event capturing은 상위 엘리먼트에서 하위 엘리먼트로 이벤트가 이동하는 것을 뜻하는데, 모던 브라우저는 이 기능을 기본적으로 제공하고 있지는 않지만, 자바스크립트 코드로 실행 할 수 있다. 

 

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>Event Capturing</title>
</head>
<body>
  <div id="parent">
    <button id="child">Child</button>
  </div>
  
  <script>
    var parent = document.querySelector('#parent');
    var child = document.querySelector('#child');

    parent.addEventListener('click', function(){
      console.log("Parent clicked");
    },true);


    child.addEventListener('click', function(){
      console.log("Child clicked");
    });
  </script>
</body>
</html>

버튼을 클릭하면, 이벤트는 부모로부터 이벤트 타켓까지 이벤트를 전달한다. Click event는 다음과 같은 순서로 전달된다. 

 

  1. document
  2. <html>
  3. <body>
  4. <div>
  5. <button>