매일 면접 질문

[매일매일] 이벤트 전파(event propagation)에 대해서 설명해주세요

개발찾아 삼만리 2024. 12. 6. 19:06

`이벤트 전파`에는 DOM(Document Object Model)에서 이벤트가 발생했을 때, 그 이벤트가 어떠한 방식으로 전파되는지를 설명하는 개념입니다.

이벤트 전파에는 크게 세 단계로 나눌 수 있습니다.

  • 캡처링(Capturing)
  • 타겟(Target)
  • 버블링(Bubbling)
<div class="grandparent">  <!-- 3단계: 버블링 -->
    <div class="parent">    <!-- 2단계: 버블링 -->
        <button>           <!-- 1단계: 타겟 -->
            클릭!
        </button>
    </div>
</div>

1. 캡처링(Capturing)

`캡처링`은 이벤트가 DOM 트리의 최상위 요소(document 또는 window)에서 시작해, 이벤트가 발생한 요소(타깃 요소)로 향해 내려가는 단계입니다. 즉, 부모에서 자식으로 아래로 내려가며 이벤트가 전파되는 단계를 `캡처링`이라고 합니다.

// 캡처링 예시
element.addEventListener('click', (e) => {
    console.log('캡처링 단계에서 실행');
}, { capture: true });

 

2. 타겟(Target)

`타겟`은 이벤트가 실제로 발생한 타겟 요소에 도달하는 단계입니다. 타겟 요소에 등록된 이벤트 리스너가 이 시점에 실행됩니다.

 

3. 버블링(Bubbling)

`버블링`은 타겟 요소에서 이벤트가 발생한 후, 다시 DOM 트리의 상위 요소들로 이벤트가 전파되어 올라가는 단계입니다. 즉, 자식에서 부모로 위로 올라가며 이벤트가 전파되는 단계를 `버블링`이라고 합니다.

// 버블링 예시
element.addEventListener('click', (e) => {
    console.log('버블링 단계에서 실행');
});

기본적으로 대부분의 이벤트는 `버블링`을 통해 전파되지만, `addEventListener`의 세 번째 인자로 `{capture : true}`를 전달하면, 캡처링 단계에서도 이벤트를 처리할 수 있습니다.

또한, 이벤트 전파를 막기 위해서는 `e.stopPropagation()`메서드를 통해 이벤트 전파를 특정 단계에서 중단할 수 있습니다.

// 이벤트 전파 중단
element.addEventListener('click', (e) => {
    e.stopPropagation();  // 이벤트 전파 중단
    console.log('여기서 전파가 멈춤');
});

💡 추가 설명

1. 버블링되지 않는 이벤트

  • `focus`, `blur`
  • `load`, `unload`, `abort`, `error`
  • `mouseenter`, `mouseleave`

위와 같은 이벤트들은 해당 요소에서만 발생하고 상위로 전파되지 않습니다.

2. 이벤트 전파 메커니즘

  • 캡처링 단계 (위에서 아래로 ↓)
  • 타켓 단계 (이벤트 발생한 요소)
  • 버블링 단계 (아래에서 위로 ↑)

3. 전파 중단 메서드 차이(stopPropagation VS stopImmediatePropagation)

  • `stopPropagtion()` : 현재 이벤트의 전파를 중단하지만, 현재 요소에 등록된 다른 이벤트 리스너는 실행됨
element.addEventListener('click', (e) => {
    e.stopPropagation();
    console.log('첫 번째 핸들러 - 실행됨');
});

element.addEventListener('click', () => {
    console.log('두 번째 핸들러 - 실행됨');
});
  • `stopImmediatePropagtion()` : 현재 이벤트의 전파를 중단하고, 현재 요소에 등록된 다른 이벤트 리스너도 실행되지 않음
element.addEventListener('click', (e) => {
    e.stopImmediatePropagation();
    console.log('첫 번째 핸들러 - 실행됨');
});

element.addEventListener('click', () => {
    console.log('두 번째 핸들러 - 실행되지 않음');
});

4. 이벤트 위임(Event Delegation)

이벤트 위임은 버블링을 활용한 이벤트 핸들링 패턴입니다.

// 이벤트 위임 예시
const ul = document.querySelector('ul');

ul.addEventListener('click', (e) => {
    if (e.target.tagName === 'LI') {
        // li 요소에 대한 처리
        console.log('Li clicked:', e.target.textContent);
    }
});

// 동적으로 li 추가해도 이벤트 핸들러가 동작
const newLi = document.createElement('li');
ul.appendChild(newLi);

이번트 위임이 가지는 장점은 다음과 같습니다.

  • 개별 핸들러 등록을 하지 않아도 되기 때문에 메모리 사용량 감소
  • 동적 요소 처리하기 용이
  • 코드 유지보수 편의성