블로그로 돌아가기
Javascript

javascript event delegation 실무 가이드: 개념부터 적용까지

javascript event delegation 개념과 실무 적용 방법을 정리합니다. 이벤트 버블링 이해부터 코드 예제, 판단 기준표, 체크리스트와 주의점까지 빠르게 적용할 수 있도록 안내합니다.

event-delegationdom-eventperformancevanilla-js
javascript event delegation을 설명하는 다이어그램이 있는 기술 블로그 썸네일

javascript event delegation이 필요한 상황

javascript event delegation은 많은 유사한 요소에 개별로 이벤트 리스너를 붙이기보다 상위 요소에 한 번만 리스너를 등록해 처리하는 패턴입니다. 이 글에서는 javascript event delegation의 핵심 개념, 실무 예제, 언제 쓰고 피해야 하는지, 성능·보안·운영 주의점과 바로 적용 가능한 체크리스트까지 제공합니다.

javascript event delegation 핵심 개념

이벤트 위임은 DOM의 이벤트 버블링을 활용합니다. 사용자가 하위 요소를 클릭하면 이벤트가 상위 노드로 전파되므로 상위 요소에서 이벤트를 잡아 하위 대상(event.target)에 따라 분기합니다. 주로 다음을 이해해야 실무 적용이 편합니다.

  • event.target: 실제 이벤트가 발생한 요소
  • event.currentTarget: 리스너가 붙은 요소
  • event.stopPropagation(): 더 이상 버블링되거나 캡처되지 않도록 중단
  • matching (예: closest or matches): 하위 요소가 관심 대상인지 판별

javascript event delegation 실무 예제

아래 예제는 동적으로 추가되는 리스트 항목에 클릭 이벤트를 위임하는 패턴입니다.

// 부모 컨테이너에 한 번만 리스너 등록 const list = document.querySelector('#todo-list'); list.addEventListener('click', (event) => { // 실제 클릭한 요소 const target = event.target; // 특정 버튼(예: 삭제 버튼)을 클릭했는지 판별 const deleteBtn = target.closest('.btn-delete'); if (deleteBtn && list.contains(deleteBtn)) { const item = deleteBtn.closest('.todo-item'); if (item) { item.remove(); } return; } // 체크박스 토글 const toggle = target.closest('.todo-toggle'); if (toggle && list.contains(toggle)) { const item = toggle.closest('.todo-item'); if (item) { item.classList.toggle('completed'); } return; } }); // 동적으로 항목 추가 function addTodo(text) { const li = document.createElement('li'); li.className = 'todo-item'; li.innerHTML = ` <span class="todo-text">${text}</span> <button class="btn-delete">삭제</button> <button class="todo-toggle">완료</button> `; list.appendChild(li); }

위 예제는 event.target과 closest를 사용해 대상 판별 후 로직을 분기합니다. 동적 생성 요소에도 별도 리스너를 붙일 필요가 없습니다.

언제 쓰면 좋고 언제 피해야 할까

언제 쓰면 좋은가:

  • 동일한 동작을 여러 하위 요소에 적용할 때
  • 동적으로 요소가 자주 추가/삭제되는 UI
  • 메모리/리스너 관리를 단순화하고 싶을 때

언제 피해야 하는가:

  • 이벤트가 부모에서 처리되면 안 되는 경우(예: 캡처/버블링 제어가 엄격한 UI)
  • 이벤트 대상이 복잡한 캘리브레이션을 요구해 판별 로직이 지나치게 무거운 경우
  • 보안상 민감한 컨트롤(예: 폼 제출의 직접 처리)을 개별 요소에서 명확히 제어해야 할 때

javascript event delegation 사용 시 비교표

구분장점단점권장 상황
개별 리스너 방식요소별 세밀 제어 가능많은 리스너로 메모리·성능 부담적은 수의 정적 요소
event delegation리스너 수 감소, 동적 요소 처리 용이타깃 판별 로직 필요, 버블링 영향동적 리스트, 반복 컴포넌트

실무 체크리스트

  • 부모 컨테이너가 이벤트를 모두 포함하는지 확인
  • event.target과 closest/matches로 정확히 판별하는가
  • stopPropagation 사용 여부와 영향 검토
  • 접근성(키보드 이벤트) 대응 여부 확인
  • 성능을 위해 불필요한 DOM 조회를 최소화했는가
  • 테스팅: 동적 요소 추가/삭제 시 동작 확인

성능·보안·운영 주의점

성능:

  • 리스너는 한 번만 등록되지만 이벤트 핸들러 내부 로직이 무겁다면 성능 저하
  • 핸들러에서 빈번한 DOM 조회(querySelector 등)를 피하고, 필요한 경우 캐싱

보안:

  • 사용자 입력을 innerHTML로 바로 주입하면 XSS 가능성 있음. 텍스트는 textContent 사용
  • 이벤트 처리로 민감한 상태를 변경할 때는 추가 검증(권한 체크) 필요

운영:

  • 로그/분석을 위해 이벤트가 중복 기록되지 않도록 설계
  • 프레임워크(React 등)와 혼용 시 Synthetic Event와 브라우저 이벤트의 차이 고려

javascript event delegation 실무 적용 팁

  • matches/closest를 적극 활용해 판별 코드를 단순화
  • 데이터 속성(data-*)로 액션 타입을 전달하면 switch 문으로 분기 가능
  • 복잡한 UI는 작은 컨테이너 단위로 위임해 범위를 제한

자주 묻는 질문

Q: 이벤트가 상위까지 올라오지 않는 경우가 있나요?

A: 네. stopPropagation이나 stopImmediatePropagation을 호출하면 버블링이 멈춥니다. 또한 Shadow DOM 내부에서는 기본 버블링 경로가 다릅니다.

Q: React 같은 라이브러리와 함께 써도 되나요?

A: DOM 직접 조작을 피하는 React에서는 권장되지 않지만, 특정 외부 라이브러리나 포탈 등 React 관리 밖의 요소에는 사용할 수 있습니다. 다만 Synthetic Event와 네이티브 이벤트 타이밍 차이를 주의하세요.

Q: delegated handler 내부에서 성능을 개선하려면?

A: 핸들러 진입 시 가능한 빠르게 타깃 판별을 하고, 불필요한 DOM 조회를 줄이며, 필요한 경우 requestAnimationFrame이나 debounce를 사용해 빈번한 작업을 제어하세요.

Q: data- 속성을 사용하면 어떨까요?

A: 권장됩니다. data-action 같은 속성으로 동작을 식별하면 matches/closest로 판별하기 쉽고 코드 가독성이 좋아집니다.

정리

  • javascript event delegation은 이벤트 버블링을 활용해 상위 요소에 리스너를 모아 관리하는 기법이다.
  • 동적 요소가 많은 UI나 반복 컴포넌트에서 유리하며 리스너 수를 줄여 메모리 관리를 단순화한다.
  • 타깃 판별 로직, 접근성, 보안(XSS)과 같은 주의점은 반드시 점검해야 한다.
  • 체크리스트를 통해 부모 범위, 판별 방법, 테스트, 성능 최적화를 확인해 적용하자.
javascript event delegation: 실무 적용 가이드 | RYUSLOG DEV