🎯 JavaScript Event Delegation 시뮬레이터

이벤트 위임을 통한 효율적인 이벤트 처리를 시각적으로 학습해보세요

🎯 이벤트 처리 모드

다른 방식으로 이벤트를 처리해보고 차이점을 확인해보세요

🔄 이벤트 전파 시뮬레이션

Event Capturing과 Bubbling 단계를 시각적으로 확인하세요

🏠 DOM 구조 시각화

📄 Document
📋 Todo Container (이벤트 리스너 등록됨)위임 모드
JavaScript 학습하기
React 프로젝트 만들기
Event Delegation 이해하기

📊 성능 메트릭

이벤트 리스너 개수
1
위임 방식
메모리 사용량
낮음
추정 값
처리된 이벤트
0
총 이벤트 수
💡 성능 비교
개별 방식: 각 요소마다 리스너 등록
위임 방식: 부모에서 한 번만 등록
메모리 절약: 위임 방식이 더 효율적

📝 실시간 이벤트 로그0

아직 이벤트가 발생하지 않았습니다. Todo 아이템을 클릭해보세요!

🧪 실험해보기

🔬 실험 1: 성능 비교

  1. 개별 리스너 모드로 전환
  2. 새 Todo를 10개 이상 추가
  3. 성능 메트릭에서 리스너 개수 확인
  4. 위임 모드로 전환하여 비교

⚡ 실험 2: Bubbling 전파

  1. "Bubbling만" 모드 선택
  2. Todo 아이템 클릭
  3. 이벤트 로그에서 Bubbling 단계만 확인
  4. 하이라이트 애니메이션 관찰

🔄 실험 3: Capturing + Bubbling

  1. "Capturing + Bubbling" 모드 선택
  2. Todo 아이템 클릭
  3. 3단계 전파 과정 관찰
  4. 각 단계별 로그와 하이라이트 확인

📚 학습 가이드: Event Delegation

실제 코드와 함께 이벤트 위임의 작동 원리를 이해해보세요

🔍 이벤트 전파와 위임의 작동 원리

📊 이벤트 전파 3단계

🔽 1. Capturing Phase
Document → 부모 → 자식 → Target
🎯 2. Target Phase
실제 이벤트가 발생한 요소에서 처리
🔼 3. Bubbling Phase
Target → 자식 → 부모 → Document

⚡ Event Delegation 원리

  1. 이벤트 전파 활용: Capturing 또는 Bubbling 단계에서 부모 요소가 자식의 이벤트를 감지합니다.
  2. 단일 리스너 등록: 부모 컨테이너에 하나의 이벤트 리스너만 등록합니다.
  3. 타겟 식별: event.target으로 실제 클릭된 요소를 확인하고 event.currentTarget으로 리스너가 등록된 요소를 확인합니다.
  4. 동적 처리: 새로 추가된 요소도 자동으로 이벤트 처리가 가능합니다.
  5. 메모리 효율: 개별 리스너 대신 하나의 리스너로 모든 이벤트를 처리합니다.

💻 핵심 코드 분석

❌ 개별 이벤트 리스너 방식

// 각 Todo 아이템마다 리스너 등록
todoItems.forEach(item => {
  const element = document.getElementById(item.id);
  
  // 완료 버튼 리스너
  const completeBtn = element.querySelector('.complete');
  completeBtn.addEventListener('click', handleComplete);
  
  // 삭제 버튼 리스너  
  const deleteBtn = element.querySelector('.delete');
  deleteBtn.addEventListener('click', handleDelete);
});

// 문제점:
// - 요소마다 여러 개의 리스너 필요
// - 메모리 사용량 증가
// - 동적 요소에 수동으로 리스너 추가 필요

✅ Event Delegation 방식

// 부모 컨테이너에 하나의 리스너만 등록
const todoContainer = document.getElementById('todoContainer');

// Bubbling 단계에서 처리 (기본값)
todoContainer.addEventListener('click', (e) => {
  const target = e.target;          // 실제 클릭된 요소
  const currentTarget = e.currentTarget; // 리스너가 등록된 요소
  const todoId = target.closest('[data-todo-id]')?.getAttribute('data-todo-id');
  
  if (target.classList.contains('complete-btn')) {
    handleComplete(todoId);
  } else if (target.classList.contains('delete-btn')) {
    handleDelete(todoId);
  }
}, false); // false = Bubbling 단계 (기본값)

// Capturing 단계에서 처리하려면:
todoContainer.addEventListener('click', (e) => {
  // 이벤트가 자식으로 전파되기 전에 먼저 처리됨
  console.log('Capturing phase:', e.currentTarget);
}, true); // true = Capturing 단계

// 장점:
// - 하나의 리스너로 모든 이벤트 처리
// - 메모리 효율적
// - 동적 요소 자동 처리
// - Capturing/Bubbling 단계 선택 가능

🎯 주요 개념

🔽 Event Capturing

이벤트가 Document에서 시작해서 타겟 요소까지 내려가는 과정입니다. addEventListener의 세 번째 매개변수를 true로 설정하면 활용할 수 있습니다.

🔼 Event Bubbling

이벤트가 타겟 요소에서 시작해서 Document까지 올라가는 과정입니다. 기본 동작이며, Event Delegation에서 주로 활용됩니다.

🎯 event.target vs currentTarget

target은 실제 클릭된 요소, currentTarget은 이벤트 리스너가 등록된 요소입니다. 위임에서는 target으로 실제 클릭 요소를 확인합니다.

⚡ 성능 최적화

하나의 이벤트 리스너로 여러 요소의 이벤트를 처리하여 메모리 사용량을 줄이고 성능을 향상시킬 수 있습니다.

🔄 동적 요소 처리

새로 추가된 요소에 별도의 이벤트 리스너를 등록할 필요 없이 자동으로 이벤트 처리가 가능합니다.

🎪 useCapture 매개변수

addEventListener(event, handler, useCapture)에서 useCapture가 true면 Capturing 단계, false면 Bubbling 단계에서 처리됩니다.

🌟 실제 사용 사례

📋 1. Todo 리스트

동적으로 추가/삭제되는 Todo 아이템들의 이벤트를 효율적으로 처리

// 테이블 행 클릭 처리
table.addEventListener('click', (e) => {
  if (e.target.matches('.edit-btn')) {
    editRow(e.target.closest('tr'));
  }
});

📊 2. 데이터 테이블

대량의 테이블 행에서 편집, 삭제 버튼 이벤트 처리

// 내비게이션 메뉴
nav.addEventListener('click', (e) => {
  if (e.target.matches('a[data-page]')) {
    loadPage(e.target.dataset.page);
  }
});

🎮 3. 게임 인터페이스

게임 보드의 여러 타일이나 버튼들의 클릭 이벤트 처리

// 게임 보드
gameBoard.addEventListener('click', (e) => {
  const tile = e.target.closest('.tile');
  if (tile) handleTileClick(tile);
});

🏪 4. 쇼핑몰 상품 목록

상품 카드의 장바구니 추가, 찜하기 등의 버튼 이벤트 처리

// 상품 목록
productGrid.addEventListener('click', (e) => {
  const productId = e.target.closest('[data-product-id]')?.dataset.productId;
  if (e.target.matches('.add-to-cart')) {
    addToCart(productId);
  }
});

🚀 성능 최적화 팁

✅ Best Practices

  • 가장 가까운 공통 부모에 리스너 등록
  • event.target으로 정확한 요소 식별
  • closest() 메서드로 조상 요소 찾기
  • 이벤트 타입별로 적절히 분리

⚠️ 주의사항

  • 이벤트 전파가 중단되면 작동 안 함
  • 너무 상위 요소에 등록하면 성능 저하
  • 복잡한 선택자는 성능에 영향
  • 필요한 경우 stopPropagation() 사용
🧑‍💻

1nnovator 김민성

JavaScript 학습 센터 개발자

기술 블로그Interactive JavaScript Learning Platform

🌟 이 프로젝트가 도움이 되셨다면 블로그에서 더 많은 개발 이야기를 확인해보세요!

🤖이 페이지는 생성형 AI의 도움을 받아 제작되었습니다.