만약 이미지 리스트에서 각 이미지 클릭시, 이미지 URL을 보여주는 기능이 필요하다고 가정해보자.

그럼, 우선 직관적으로 모든 이미지 Element에 대한 addEventListener() 함수에 click 이벤트 핸들러를 등록하는 것을 생각할 수 있다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
    <style>
        li {list-style:none;}

        ul > li {
            display:inline-block;
            padding:10px;
            border:1px solid gray;
        }

        .image {
            width:200px;
            height:auto;
        }
    </style>
</head>
<body>
<ul>
    <li>
        <img src="<https://upload.wikimedia.org/wikipedia/commons/d/d6/Horse_2005-08-06_%28Cheval%29.jpg>" class="image">
    </li>
    <li>
        <img src="<https://image.dongascience.com/Photo/2019/05/3e95c45fbe6710365e999ebbd32ed37e.jpg>" class="image">
    </li>
    <li>
        <img src="<https://pds.joins.com/news/component/htmlphoto_mmdata/201906/18/f3eb4268-ecf0-40c6-a23a-62dd99d0d5fd.jpg>" class="image">
    </li>
    <li>
        <img src="<https://img.hani.co.kr/imgdb/resize/2017/1121/00504228_20171121.JPG>" class="image">
    </li>
    <li>
        <img src="<https://blog.hmgjournal.com/images/contents/article/201603211108-Reissue-pet-family-01.jpg>" class="image">
    </li>
</ul>

<div></div>

<script>
    const target = document.querySelector('div');
    const images = document.querySelectorAll('img');
    for(let image of images) {
        image.addEventListener('click', function(event) {
            target.innerHTML = "Image url : " + event.currentTarget.src ;
        });
    }
</script>
</body>
</html>

위 예제와 같이, 모든 Image에 대한 <li> Element 리스트 찾아서 이벤트를 등록하여 처리하였다. 하지만, 이러한 방법은 리스트의 크기가 길어질 경우 메모리를 많이 차지하고 브라우저에서 관리해야 하는 핸들러가 증가하게 된다.

뿐만 아니라 새로운 이미지를 동적으로 추가하게 된다면, 새로운 이미지에 대한 동일한 Event Handler를 addEventListner()에 등록하는 코드가 필요로 하게 된다..;

따라서, 이를 효율적으로 처리하기 위한 방법이 필요한데, 이는 Event Bubbling/Capturing을 이용해서 간단하게 처리할 수 있다.

그럼 Event Bubbling과 Event Capturing 란 무엇일까

Event Bubbling은 특정 Element에서 이벤트가 발생했을때, 자신의 HTML 트리 구조상의 조상 element들에게 이벤트를 전달하는 것을 의미한다.

이와 반대로, Event Capturing은 특정 Element에서 이벤트가 발생했을때, 자신의 HTML 트리 구조상의 자손 element들에게 이벤트를 전달하는 것을 의미한다.

Event Bubbling, Event Capturing은 addEventListner() 함수에서 설정한다. Event Bubbling은 Default 이고, Event Capturing은 옵션 객체로 capture: true를 전달한다.

만약 element.addEventListner() 함수를 통해 동일한 요소에 다른 핸들러를 등록하면 어떻게 될까? 두 핸들러 모두 실행된다.

지금부터의 설명은 Event Bubbling을 가정해 설명하겠다.(Event Bubbling는 반대로 생각하면 된다.)

그렇다면, 상위 Element는 어느 하위 Element에서 이벤트가 발생했는지 알수 있을까?

이러한 경우를 위해서, 핸들러를 통해 전달되는 Event 객체는 currentTargettarget 프로퍼티를 가진다. 구체적으로, currentTarget는 현재 element(즉, 이벤트를 전달받은 상위 요소)를 가리키고, target은 이벤트가 발생한 Element를 가리킨다.

아래 예제를 보자.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
<ul>
    <li>
        <img src="<https://upload.wikimedia.org/wikipedia/commons/d/d6/Horse_2005-08-06_%28Cheval%29.jpg>" class="image">
    </li>
</ul>
<script>
    const ul = document.querySelector('ul');
    ul.addEventListener('click', function(event) {
        console.log(event.currentTarget, event.target);
    });
</script>
</body>
</html>

img 요소에서 클릭이 발생했다고 가정하자. ul 요소에 click 이벤트에 대한 핸들러에서는 아래와 그림같이 현재 currentTargetul 요소와 targetimg 요소를 순차적으로 출력할 것이다.