1. 이벤트 위임이란 무엇인가
이벤트 위임(Event Delegation)은 말 그대로
“하위 요소의 이벤트를 상위 요소가 대신 처리하는 방식”이다.
HTML 구조 예시 👇
<ul id="menu">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
보통은 이렇게 각 <li>에 클릭 이벤트를 하나씩 걸지만 —
document.querySelectorAll("li").forEach((item) => {
item.addEventListener("click", () => console.log(item.textContent));
});
이건 비효율적이야.
<li>가 100개라면 이벤트 리스너도 100개 생기고,
동적으로 추가된 항목에는 작동하지 않아.
그래서 이렇게 바꾼다 👇
document.getElementById("menu").addEventListener("click", (e) => {
if (e.target.tagName === "LI") {
console.log("클릭된 메뉴:", e.target.textContent);
}
});
✅ 이벤트는 한 번만 등록
✅ 새로 추가된 <li>도 자동으로 반응
✅ 코드 간결 + 메모리 절약
이게 바로 이벤트 위임(Event Delegation) 의 본질이다.
2. 이벤트 위임의 동작 원리
이벤트 위임이 가능한 이유는 버블링(Bubbling) 덕분이다.
즉, 하위 요소에서 발생한 이벤트가 상위로 전달되기 때문에
상위 요소에서 그 이벤트를 대신 감지할 수 있는 것이다.
<div id="parent">
<button>클릭</button>
</div>
document.getElementById("parent").addEventListener("click", (e) => {
console.log("이벤트 감지:", e.target.tagName);
});
→ button을 클릭해도, 이벤트는 parent까지 전달되어 실행된다.
→ 따라서 상위에서 하위를 “대신 감시”할 수 있다.
3. 실전 예제 — To-Do 리스트
아래 예시는 동적으로 생성된 항목에도
자동으로 이벤트가 작동되는 실무형 예시다.
<input id="taskInput" placeholder="할 일을 입력하세요" />
<button id="addBtn">추가</button>
<ul id="taskList"></ul>
<script>
const input = document.getElementById("taskInput");
const addBtn = document.getElementById("addBtn");
const list = document.getElementById("taskList");
addBtn.addEventListener("click", () => {
const text = input.value.trim();
if (!text) return alert("내용을 입력하세요!");
const li = document.createElement("li");
li.innerHTML = `${text} <button class="delete">삭제</button>`;
list.appendChild(li);
input.value = "";
});
list.addEventListener("click", (e) => {
if (e.target.classList.contains("delete")) {
e.target.parentElement.remove();
}
});
</script>
✅ 리스트에 새 항목이 추가되어도 “삭제 버튼”이 자동 작동
✅ querySelectorAll로 새 버튼을 다시 탐색할 필요 없음
이게 바로 이벤트 위임의 강력한 장점이다.
4. 이벤트 위임의 장점
항목 설명
| 💡 성능 향상 | 리스너 개수가 줄어들어 메모리 절약 |
| 🔄 동적 요소 대응 | Ajax나 DOM 추가 후에도 자동 적용 |
| 🧩 유지보수 편의성 | 중앙 집중식 제어로 코드 간결 |
| ⚡ React와 유사한 구조 | 실제 React도 이벤트 위임 방식으로 동작 |
5. 조건 분기와 타깃 확인
복잡한 구조에서도 e.target을 활용해
클릭된 요소의 정보를 정확히 구분할 수 있다.
<ul id="list">
<li data-id="1"><span>HTML</span> <button class="edit">수정</button></li>
<li data-id="2"><span>CSS</span> <button class="edit">수정</button></li>
</ul>
<script>
document.getElementById("list").addEventListener("click", (e) => {
const item = e.target.closest("li");
if (!item) return;
if (e.target.classList.contains("edit")) {
const id = item.dataset.id;
console.log(`ID ${id} 수정 버튼 클릭`);
} else if (e.target.tagName === "SPAN") {
console.log(`항목 클릭: ${item.dataset.id}`);
}
});
</script>
✅ closest()는 가장 가까운 상위 요소를 탐색 (React의 delegation 구조와 유사)
✅ dataset으로 각 항목의 고유 식별자 접근 가능
6. 성능 비교 — 직접 이벤트 vs 위임 이벤트
비교 항목 개별 이벤트 이벤트 위임
| 리스너 개수 | N개 (요소마다) | 1개 |
| 메모리 사용량 | 많음 | 적음 |
| 동적 요소 처리 | 새로 추가 시 다시 등록 필요 | 자동 적용 |
| 유지보수 | 어렵고 반복적 | 간결하고 체계적 |
➡ 리스트나 테이블, 갤러리처럼 요소가 많을수록 이벤트 위임의 효율이 폭발적으로 증가한다.
7. 이벤트 위임의 주의점
✅ e.target이 정확히 클릭한 요소를 반환하므로,
내부에 다른 태그가 있으면 의도치 않은 동작이 발생할 수 있다.
→ 이런 경우엔 closest() 또는 matches()로 범위를 제한하자.
if (e.target.closest("button.delete")) {
// 삭제 버튼만 감지
}
✅ 이벤트가 버블링되지 않는 일부 이벤트에는 적용할 수 없다.
(예: focus, blur, mouseenter, mouseleave 등은 버블링 X)
대신 focusin, focusout 같은 버블링 가능한 대체 이벤트를 사용한다.
8. 실무 응용 — 카드형 UI 클릭 관리
<div id="cards">
<div class="card" data-id="1"><h3>HTML</h3></div>
<div class="card" data-id="2"><h3>CSS</h3></div>
<div class="card" data-id="3"><h3>JavaScript</h3></div>
</div>
<script>
const cards = document.getElementById("cards");
cards.addEventListener("click", (e) => {
const card = e.target.closest(".card");
if (!card) return;
alert(`${card.querySelector("h3").textContent} 카드 클릭됨`);
});
</script>
✅ 클릭된 카드만 인식
✅ 추가된 카드도 자동 반응
✅ 실제 React에서 카드 리스트를 map으로 그릴 때와 거의 동일한 구조
9. 이벤트 위임 + IntersectionObserver (고급 응용)
이벤트 위임은 “사용자 상호작용”뿐 아니라
스크롤 감지, 무한 스크롤, Lazy Loading 등과 결합해 성능 최적화에도 활용된다.
const list = document.getElementById("productList");
list.addEventListener("click", (e) => {
if (e.target.matches(".load-more")) {
loadMoreItems();
}
});
→ 한 개의 상위 이벤트로 모든 하위 “로드 버튼” 관리 가능.
10. 정리
개념 설명
| 이벤트 위임 | 상위 요소가 하위 요소의 이벤트를 대신 처리 |
| 핵심 원리 | 이벤트 버블링 |
| 장점 | 성능 향상, 코드 간결, 동적 요소 대응 |
| 실무 활용 | 리스트, 카드, 모달, 메뉴, 무한 스크롤 등 |
| 주의점 | focus, mouseenter 등 비버블 이벤트 예외 처리 필요 |
11. 마무리
이제 이벤트 위임의 구조를 완전히 이해했다면,
DOM의 이벤트를 “조작”하는 게 아니라 “관리”하는 개발자로 한 단계 성장한 거야.
이 패턴은 단순한 트릭이 아니라,
대규모 UI를 효율적으로 제어하는 근본적인 철학이야.
“이벤트를 줄이는 것은 코드의 수를 줄이는 게 아니라,
브라우저의 일을 줄이는 것이다.”
'frontend > javascript' 카테고리의 다른 글
| 🟨 2-17. this 완전 정복 — 함수, 객체, 클래스에서의 this 바인딩 규칙과 혼동 포인트 (0) | 2025.11.07 |
|---|---|
| 🟨 2-16. 자바스크립트 이벤트 루프와 콜스택 — 비동기 코드의 진짜 실행 순서 이해하기 (0) | 2025.11.07 |
| 🟨 2-14. 이벤트 버블링과 캡처링 완벽 이해 — 브라우저 이벤트 흐름의 핵심 메커니즘 (0) | 2025.11.07 |
| 🟨 2-13. 자바스크립트 DOM 완전 이해 — HTML 문서를 제어하는 핵심 원리와 실전 예제 (0) | 2025.11.07 |
| 🟨 2-12. JSON과 데이터 구조 완전 이해 — 서버와 클라이언트 간 데이터 교환의 핵심 포맷 (0) | 2025.11.07 |