"매 DOM event 는 capture → target → bubble 3-phase 의 propagation". Events 는 user/system action (click, input, scroll, ...) 을 JS handler 에 dispatch 하는 mechanism. 매 modern app 의 React SyntheticEvent / addEventListener / passive listener 의 mix 의 사용.
Custom: new CustomEvent('foo', { detail: {...} }).
매 응용
UI interaction (button click, form submit).
Event delegation (single listener for many children).
Drag-and-drop (pointer events).
Keyboard shortcuts / accessibility.
💻 패턴
Basic addEventListener
button.addEventListener('click',(e)=>{console.log('clicked',e.target);});// removeEventListener requires same fn reference
consthandler=(e)=>console.log(e);el.addEventListener('click',handler);el.removeEventListener('click',handler);
Event Delegation
// Single listener on parent — handles all child clicks
document.querySelector('#list').addEventListener('click',(e)=>{constitem=e.target.closest('[data-id]');if(!item)return;console.log('item:',item.dataset.id);});
Passive Listener (Scroll Performance)
// Tells browser handler won't preventDefault → no scroll-blocking
window.addEventListener('scroll',onScroll,{passive:true});window.addEventListener('touchmove',onTouchMove,{passive:true});
AbortController (modern cleanup)
constctrl=newAbortController();el.addEventListener('click',handler,{signal:ctrl.signal});el.addEventListener('mouseover',other,{signal:ctrl.signal});// Remove all at once
ctrl.abort();
언제: event listener pattern 의 question, propagation 의 debug, delegation 의 implement.
언제 X: framework-specific event system 의 deep dive (React/Vue 의 own docs 의 참조).
❌ 안티패턴
Inline onclick="" attribute: HTML/JS 의 mix, CSP 의 violation.
No cleanup in SPA: memory leak. 매 unmount 의 removeEventListener 의 호출.
scroll without passive: 60fps scroll 의 block.
stopPropagation() overuse: delegation pattern 의 break.
Listener on every list item: N 의 listener 대신 delegation 의 사용.
🧪 검증 / 중복
Verified (MDN Web Docs — Event reference, WHATWG DOM spec).