# 이벤트 위임

{% hint style="info" %}
[**모던 자바스크립트 듀토리얼**](https://ko.javascript.info/bubbling-and-capturing)
{% endhint %}

## 이벤트 위임

> 문제의 시작은 리스트로 된 요소에 이벤트를 거는 곳에서 시작됐다....

## HTML 요소에 이벤트 걸기

일반적인 HTML 요소에 이벤트를 거는 방법은... 처음 배우는 사람도 금방 할 수 있을 만큼 쉽다.

네모난 박스를 누르면 `console.log` 를 하는 html과 이벤트를 만들어보자.

```markup
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>기본</title>
  <style>
    #box {
      width: 100px;
      height: 100px;
      background: #f06292;
    }
  </style>
</head>

<body>
  <div id="box"></div>
  <script>
    document.querySelector("#box").addEventListener("click", function () {
      alert("이벤트입니다.");
    });
  </script>
</body>

</html>
```

위와 같은 코드를 실행하면 아래와 같이 출력되는걸 확인할 수 있다.

![아주 기본적인 이벤트!](/files/-MW-OGYRfkS1YepYz2Fn)

## 겹쳐져있는 요소에 이벤트 걸기

```markup
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>자바스크립트 이벤트</title>
  <style>
    .box {
      width: 100px;
      height: 100px;
      background: #f06292;
    }
  </style>
</head>

<body>
  <div class="one box">
    <div class="two box">
      <div class="three box">
      </div>
    </div>
  </div>
  <script>


    var boxs = document.querySelectorAll('.box');
    boxs.forEach(function (box) {
      box.addEventListener('click', logEvent);
    });

    function logEvent(event) {
      console.log(event.currentTarget.className);
    }
  </script>
</body>

</html
```

위 코드를 보면 **3개의 div요소가 겹쳐져 있다.** 그리고 **querySelectorAll** 을 통해서 모든 **box 클래스를 갖는 div 를 찾고 이벤트를 건다.** 클릭해보기전에 예측을 해보자면 겹쳐있다고는 해도 실제 사용자에게 보여지는 요소는 마지막 3번째 요소이므로 **three box** 하나가 출력되었을거같다.

자, 이제 브라우저에서 요소를 클릭해보자.

![이벤트 버블링](/files/-MW-OGYSGajE1Fn36vi4)

**오잉... 무슨 일이지 대체 왜 3개 모두 찍힌거야?**

### event bubbling

콘솔로그로 출력된 걸 보면 가장 마지막 요소부터 처음요소까지 위로 올라오면서 동작이 됐다는걸 알 수 있다. **이벤트 버블링이란 한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고 이어서 부모 요소의 핸들러가 동작한다는 것이다. 그리고 가장 최상단의 조상 요소를 만나기 전까지 이 과정이 반복되는 과정을 말한다.**

따라서 네모 박스를 클릭했을 때 아래와 같은 동작이 수행된다.

1. 가장 안쪽의 div에서 클릭이벤트가 발생
2. 바깥의 div에서 클릭이벤트가 발생
3. 그 바깥으 이벤트 핸들러가 동작....
4. document 객체를 만날 때 까지 이벤트 핸들러가 동작한다.

**logEvent** 를 약간 수정해서 **event** 자체를 출력해보자.

![](/files/-MW-OGYTa4KGcL98Mgbc)

**console.log(event)** 에서 **path** 를 보면 이렇게 되어있다. 클릭이벤트가 **three box** 부터 끝까지 타고 올라가는걸 확인할 수 있다.

### 이벤트 캡쳐링

버블링과는 반대로 **상위에서 하위로 뻗어 나간다.** 위의 예제에서 `capture: true` 라는 옵션만 주면 확인할 수 있다.

캡쳐링은 클릭 이벤트가 발생한 지점을 찾아내려가는 이미지를 상상하면 된다.

## stopPropagation

이렇게 이벤트가 위로 올라가고.... 아래로 내려가는데 보통의 경우 이는 개발자가 원하지 않는 상황이다. 이 문제으 해결방법은 코드를 구조적으로 짜는게 가장 좋겠지만, 어쩔 수 없는 경우에는 그 자리에서 즉각적으로 버블링과 캡쳐링을 막아야만 한다. 이 때 사용하는 문법이 **stopPropagation** 이다.

## 이벤트 위임

이벤트 위임이란 **하위 요소에 각각 이벤트를 붙이지 않고 상위 요소에서 하위 요소의 이벤트들을 제어하는 방식**이다.

```markup
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title> no event delegation</title>
</head>

<body>
  <h1>오늘의 할 일</h1>
  <ul class="itemList">
    <li>
      <input type="checkbox" id="item1">
      <label for="item1">이벤트 버블링 학습</label>
    </li>
    <li>
      <input type="checkbox" id="item2">
      <label for="item2">이벤트 캡쳐 학습</label>
    </li>
  </ul>

  <script>

    var inputs = document.querySelectorAll('input');
    inputs.forEach(function (input) {
      input.addEventListener('click', function (event) {
        alert('clicked');
      });
    });

  </script>
</body>

</html
```

위의 코드는 쿼리 셀렉터를 통해서 모든 input box 를 찾고 각 요소에 클릭 이벤트 리스너를 추가하는 예제다. 눈으로 봐도 문제가 없고 실제로 실행해도 문제가 없다.

**하지만 이 코드는 문제가 있다.** 만약 새로운 할일 목록을 추가할 때 마다 이벤트 리스너를 달아줘야 하기 때문. 즉 동적인 프로그래밍이 불가능해지는 코드를 만드는 행위다.

자바스크립트 코드만 아래처럼 바꿔보자.

```javascript
var itemList = document.querySelector('.itemList');
itemList.addEventListener('click', function(event) {
    alert('clicked');
});
```

이렇게 되면 이벤트 위임의 정의대로 상위 요소 하나에 이벤트를 등록했을 뿐인데 그 하위요소에서는 해당 이벤트를 리슨할 수 있게 된다. 심지어 동적으로 추가된 요소들도 자동으로 이벤트를 듣게된다!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://simian114.gitbook.io/blog/undefined/javascript/untitled.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
