

버튼 하나를 눌렀는데 부모 목록이 같이 반응하는 상황은 버그처럼 보여요. 하지만 DOM 이벤트는 원래 그렇게 움직여요. 이 흐름을 모르고 코드를 짜면 모달 닫기, 목록 선택, 분석 로그가 서로 충돌해요.
이벤트 전파는 세 단계로 움직여요
DOM 이벤트는 보통 세 단계로 설명해요.
| 단계 | 흐름 | 의미 |
|---|---|---|
| 캡처링 | 바깥에서 안쪽으로 | 문서에서 타깃까지 내려와요 |
| 타깃 | 실제 요소 | 사용자가 클릭한 지점이에요 |
| 버블링 | 안쪽에서 바깥으로 | 부모 요소로 다시 올라가요 |
대부분의 UI 코드는 버블링을 기준으로 돌아가요. 그래서 button에 걸린 클릭이 부모 div, 그 위의 section, document까지 이어질 수 있어요. 이 특성 때문에 이벤트 위임이 가능해요.
document.querySelector('.list')?.addEventListener('click', (event) => {
if (!(event.target instanceof Element)) return;
const button = event.target.closest('button[data-id]');
if (!button) return;
const itemId = button.getAttribute('data-id');
if (!itemId) return;
// 클릭한 항목만 처리해요
});
버튼마다 리스너를 붙이지 않아도 되고, 나중에 동적으로 추가된 항목도 자연스럽게 처리돼요.
target과 currentTarget은 같은 값이 아니에요
이벤트를 읽을 때 가장 자주 헷갈리는 값이 target과 currentTarget이에요.
event.target: 실제로 클릭된 요소예요.event.currentTarget: 리스너를 붙인 요소예요.
목록 전체에 리스너를 붙였는데, 실제 클릭 대상은 안쪽의 아이콘일 수 있어요. 이때 target만 믿으면 잘못된 요소를 읽기 쉬워요. 이벤트 위임을 쓸 때는 closest()로 의도를 가진 요소를 다시 찾아야 해요.
list.addEventListener('click', (event) => {
console.log(event.target); // 실제 클릭된 요소
console.log(event.currentTarget); // 리스너가 붙은 요소
});
이 두 값이 다르다는 사실만 기억해도 디버깅 시간이 많이 줄어요.
캡처링은 예외적으로 써요
캡처링은 흔한 선택은 아니에요. 하지만 먼저 관찰해야 하는 상황에서는 유용해요. 전역 단축키, 분석 로그, 외부 클릭 감지처럼 하위 컴포넌트가 이벤트를 막기 전에 먼저 확인해야 할 때가 여기에 들어가요.
window.addEventListener(
'click',
() => {
// 문서 전체의 클릭을 먼저 관찰해요
},
true
);
세 번째 인자에 true를 넣으면 캡처링 단계에서 실행돼요. 기본값은 버블링이에요.
전파를 멈추는 함수도 비슷하게 신중하게 써야 해요. event.stopPropagation()은 부모로 올라가는 흐름을 막고, stopImmediatePropagation()은 같은 요소에 붙은 나머지 리스너까지 멈춰요. 이 차이를 모른 채 전파를 끊으면 나중에 모달, 드롭다운, 추적 코드가 서로 간섭해요.
이벤트 위임이 유리한 이유예요
이벤트 전파를 이해하면 코드가 단순해져요. 예를 들어 목록 아이템이 수십 개이고, 앞으로 더 늘어날 수 있다면 각 항목에 리스너를 붙이는 대신 부모 하나에 리스너를 두는 편이 나아요.
이 방식은 메모리 사용량보다도 구조가 단순하다는 점이 중요해요. 새로운 항목을 렌더링할 때마다 이벤트를 다시 연결할 필요가 없고, 삭제된 요소의 리스너를 따로 정리할 일도 줄어요.
다만 전파를 막는 코드는 최소한으로 두는 편이 좋아요. 이벤트 위임이 잘 돌아가는 구조에서 stopPropagation()을 많이 쓰기 시작하면, 나중에 다른 기능이 같은 이벤트를 쓰기 어려워져요.
정리
- DOM 이벤트는 캡처링, 타깃, 버블링 순서로 움직여요.
target과currentTarget은 역할이 달라서 구분해서 읽어야 해요.- 전파를 멈추는 코드는 이유를 같이 남겨야 유지보수가 쉬워요.


