의도: 이벤트 버블링과 캡처링에 대해 잘 이해하고 있는지 재확인 및 위임을 이용해 최적화를 할 수 있는지 확인하기 위한 질문
팁: 최적화 얘기를 하면 좋다.
나의 답안
이벤트 위임은 부모 요소에 이벤트를 설정하여 자식 요소에서 발생하는 이벤트를 처리하는 기술입니다.
자바스크립트에서 이벤트를 효율적으로 관리하기 위해 널리 사용됩니다.
이벤트 위임은 브라우저의 이벤트 버블링 개념을 기반으로 작동합니다.
이벤트 버블링은 특정 요소에서 이벤트가 발생하면, 그 이벤트는 DOM 트리 상의 부모 요소로 전파됩니다.
따라서, 자식 요소 각각에 이벤트 리스너를 설정하지 않고 부모 요소에 한 번만 리스너를 설정해도 자식에서 발생한 이벤트를 감지하고 처리할 수 있습니다.
이벤트 위임은 여러 가지 이점이 있습니다.
우선, 이벤트 위임은 많은 자식 요소 각각에 이벤트 리스너를 붙이는 대신 부모 요소 하나에만 리스너를 붙여서 메모리 사용량을 줄이고 성능을 향상시킬 수 있습니다.
또한, DOM에 나중에 추가된 자식 요소에도 자동으로 이벤트를 적용할 수 있으므로 기존 요소에만 이벤트를 붙이는 것보다 유연합니다.
마지막으로, 리스너를 한 곳에서 관리하므로 코드가 단순해지고 유지보수가 쉬워집니다.
이렇게 이벤트 위임은 많은 이점이 있기 떄문에, 리스트, 테이블 등 많은 자식 요소가 반복되는 구조이거나, 동적으로 추가 또는 삭제되는 DOM 요소가 많은 경우에는 이벤트 위임을 적극 활용하면 좋습니다.
주어진 답안 (모범 답안)
이벤트 위임은 하위 요소의 이벤트를 상위 요소로 위임하는 걸 뜻합니다.
하위 요소가 많을 경우, 이러한 모든 요소들에 이벤트를 등록하고 관리하는 건 힘든 일이 될 수 있습니다.
그래서 버블링과 캡처링을 활용해 상위 요소에 이벤트를 위임하고, 이벤트 함수 내에서 하위 요소를 판단하여 이벤트를 처리하면 성능을 최적화할 수 있는 장점을 가진 게 바로 이벤트 위임입니다.
이벤트 위임(Event Delegation)은 부모 요소에 이벤트를 설정하여 자식 요소에서 발생하는 이벤트를 처리하는 기술이다.
자바스크립트에서 이벤트를 효율적으로 관리하기 위해 널리 사용된다.
이벤트 위임은 브라우저의 이벤트 버블링(Event Bubbling) 개념을 기반으로 작동한다.
예시)
자식 요소에서 클릭 이벤트가 발생하면, 이 이벤트는 부모 → 조상 요소까지 전파된다.
따라서, 자식 요소 각각에 이벤트 리스너를 설정하지 않고 부모 요소에 한 번만 리스너를 설정해도 자식에서 발생한 이벤트를 감지하고 처리할 수 있다.
성능 개선
많은 자식 요소 각각에 이벤트 리스너를 붙이는 대신 부모 요소 하나에만 리스너를 붙여서 메모리 사용량을 줄이고 성능을 향상시킬 수 있다.
동적으로 생성된 요소 처리
DOM에 나중에 추가된 자식 요소에도 자동으로 이벤트를 적용할 수 있다. 기존 요소에만 이벤트를 붙이는 것보다 유연하다.
코드 간결화
리스너를 한 곳에서 관리하므로 코드가 단순해지고 유지보수가 쉬워진다.
기본 구현
target 속성을 사용해 실제 이벤트가 발생한 자식 요소를 확인한다.matches() 메서드로 특정 요소에만 이벤트를 처리한다.코드 예제
<ul id="parent">
<li class="child">Item 1</li>
<li class="child">Item 2</li>
<li class="child">Item 3</li>
</ul>
document.getElementById("parent").addEventListener("click", function(event) {
// 이벤트 발생한 실제 요소를 확인
const target = event.target;
// 특정 조건의 자식 요소에만 이벤트 처리
if (target.matches(".child")) {
console.log(`Clicked on: ${target.textContent}`);
}
});
#parent에 이벤트 리스너를 추가한다.event.target으로 실제 클릭된 요소를 확인한다.target.matches('.child')로 특정 클래스의 자식만 처리한다.일반적인 이벤트 리스너는 DOM에 존재하는 요소에만 적용된다.
하지만 이벤트 위임은 새롭게 추가된 요소에도 동작한다.
// 새롭게 추가된 요소도 클릭 이벤트 처리
document.getElementById("parent").addEventListener("click", function(event) {
const target = event.target;
if (target.matches('.child')) {
console.log(`Dynamic element clicked: ${target.textContent}`);
}
});
// 새로운 요소 추가
const newChild = document.createElement('li');
newChild.className = 'child';
newChild.textContent = 'Item 4';
document.getElementById('parent').appendChild(newChild);
위 코드는 새로 추가된 Item 4에도 이벤트가 정상적으로 동작한다.
이벤트 전파 제한
자식 요소에서 event.stopPropagation()을 호출하면 버블링이 중단되어 이벤트 위임이 작동하지 않는다.
성능 문제
너무 많은 이벤트가 버블링되면 부모 요소에서 모든 이벤트를 처리해야 하므로 비효율적일 수 있다. 조건문을 적절히 사용해 이벤트 처리를 제한해야 한다.
CSS의 pointer-events와 충돌
요소가 클릭되지 않게 하기 위해 CSS에서 pointer-events: none;을 사용하는 경우, 해당 요소는 이벤트를 트리거하지 않는다.
이벤트 위임이 적합하지 않은 경우
부모와 자식 요소의 이벤트가 논리적으로 전혀 관련이 없는 경우에는 이벤트 위임을 사용하지 않는 것이 좋다.
기본적으로 이벤트 위임은 버블링을 이용하지만, 이벤트 캡처링(부모 → 자식 순으로 이벤트 전파)을 사용할 수도 있다.
addEventListener의 세 번째 매개변수로 capture: true를 설정하면 캡처링 단계에서 이벤트를 처리할 수 있다.
document.getElementById('parent').addEventListener(
"click",
function(event) {
console.log("Capturing phase: ", event.target);
},
{ capture: true }
);