블로그
Event Propagation: 버블링과 캡처링
- 등록일
- 2025-01-06 14:33:19
- 조회수
- 85
안녕하세요, Softeer 개발 인턴 소현입니다.
프론트엔드 개발에 있어서 다양한 UI 요소 간의 상호작용을 구현하기 위해 이벤트 처리(event handling)가 중요합니다.
이 과정에서 자주 접하게 되는 개념이 바로 이벤트 버블링과 캡처링입니다.
이러한 개념을 제대로 이해하고 활용하면 불필요한 이벤트 실행을 방지하고, 사용자 경험을 개선할 수 있는데요.
이번 글에서는 예제를 통해 이벤트 버블링과 캡처링의 기본 개념과 적용 사례에 대해 살펴보겠습니다.
1. 이벤트 버블링과 캡처링
이벤트 버블링과 캡처링은 이벤트가 DOM 요소들 사이에서 어떻게 전파되는지를 설명하는 두 가지 방식입니다.
- 이벤트 버블링: 이벤트가 발생한 요소에서 시작해 부모 요소로 전파되며, 최상단의 루트 요소에 도달할 때까지 전파됩니다.
- 이벤트가 발생한 요소에서 점점 바깥쪽으로 퍼져 나가는 과정
- 기본적인 DOM 이벤트 모델에서는 버블링이 디폴트로 설정되어 있습니다.
- 이벤트 캡처링: 반대로 이벤트가 가장 외부의 부모 요소에서 시작해 안쪽의 자식 요소로 전파됩니다.
- addEventListener에서 capture: true 옵션을 설정하면 활성화됩니다.
이 두 가지 방식은 특정 상황에서 의도치 않은 동작을 피하거나 특정 이벤트만 처리되도록 하는 데 중요한 역할을 합니다.
예제: 중첩된 클릭 이벤트 처리
당신은 웹 애플리케이션 개발자입니다.
·---------------------------· | ·---· | | | x | Item Title | | ·---· | ·---------------------------·
위의 예제에서, 두 개의 중첩된 DOM 요소가 있습니다. 바깥쪽 요소를 outer, 안쪽 요소를 inner라고 가정해 보겠습니다.
outer 내부를 클릭하면 추가적인 정보를 띄웁니다.
inner 내부를 클릭하면 해당 아이템을 선택된 상태로 만들고자 합니다.
outer 와 inner 의 onclink 이벤트 리스너를 구현할 때 고려해야 하는 것은 무엇인가요?
그것을 제대로 고려하지 않으면 어떤 문제가 발생하나요?
→ outer와 inner의 onclick 이벤트 리스너를 구현할 때 버블링에 대해 고려하지 않는다면,
이벤트 버블링으로 인해 원하지 않은 상위 이벤트까지 이벤트가 전파(Event Propagation)되는 문제가 발생할 수 있습니다.
<div class="outer" onclick="showAdditionalInfo()"> <div class="inner" onclick="selectItem()"> Item Title </div> </div>
위의 코드에서 사용자가 inner 요소를 클릭하면, 이벤트 버블링으로 인해 inner의 selectItem() 함수뿐만 아니라 outer의 showAdditionalInfo() 함수도 호출됩니다.
inner에서 발생한 클릭 이벤트가 상위 요소로 전파되면서 outer의 클릭 핸들러까지 실행되기 때문입니다.
이를 해결하려면, event.stopPropagation()을 사용하여 inner 요소에서 이벤트가 상위 요소로 전파되지 않도록 막아야 합니다.
function selectItem(event) { event.stopPropagation(); } // 아이템 선택 로직
해당 코드를 적용하면, inner 요소를 클릭할 때 selectItem() 함수만 호출되고, outer의 showAdditionalInfo() 함수는 호출되지 않습니다.
2. 이벤트 캡처링 적용
캡처링은 이벤트가 바깥쪽 부모에서부터 자식 요소로 전달되는 방식입니다.
캡처링은 드물게 사용되지만, UI의 계층 구조가 복잡한 경우 유용할 수 있습니다.
이를 구현하려면 addEventListener에 { capture: true } 옵션을 설정해야 합니다.
document.querySelector('.outer').addEventListener('click', showAdditionalInfo, { capture: true });
이 경우, inner 요소를 클릭하더라도 outer의 이벤트 핸들러가 먼저 실행되고, 그 이후에 inner의 이벤트 핸들러가 실행됩니다.
이는 때때로 이벤트 처리 순서를 제어하는 데 유용할 수 있습니다.
실무 적용 사례: 중첩된 이벤트 처리
프론트엔드 개발에서 이벤트 버블링 문제는 매우 흔하게 접할 수 있습니다.
예를 들어, 아래와 같은 UI 구조를 가진 코드가 있습니다.
<div class="thread-wrapper" @click="openDetailPage"> <div class="conv"></div> <button @click="deleteItem"><img class="del" src="/app/ai-chat/candi/icon_del.png" /></button> </div>
위 코드는 채팅 스레드를 표시하면서 각 스레드의 삭제 아이콘을 눌렀을 때 해당 스레드가 삭제되는 기능을 구현한 예제입니다.
그러나, 문제는 삭제 아이콘을 클릭했을 때, 스레드 자체의 상세 페이지로 이동하는 이벤트가 함께 발생하는 것이었는데요.
아래 그림과 같이 이벤트 버블링 때문에 발생한 문제로, 삭제 이벤트와 상세 페이지 이동 이벤트가 모두 전파된 것입니다.
이 문제를 해결하기 위해 Vue.js에서는 .stop Modifier를 사용해 상위 이벤트로의 전파를 중지할 수 있습니다.
<button @click.stop="deleteItem"> <!-- .stop으로 이벤트 전파 방지 --> <img class="del" src="/app/ai-chat/candi/icon_del.png" /> </button>
위와 같이 .stop을 사용하면 삭제 버튼을 클릭할 때 이벤트가 상위 요소로 전파되지 않고, 상세 페이지로의 이동도 방지됩니다.
결론
이벤트 버블링과 이벤트 캡처링은 자바스크립트의 이벤트 전파 모델의 중요한 부분이며, 이를 잘 이해하고 적절히 활용하면 복잡한 UI를 보다 효율적으로 처리할 수 있습니다.
특히, 여러 중첩된 UI 요소가 있는 상황에서 의도치 않은 동작을 방지하거나, 효율적인 이벤트 처리를 위해 이벤트 전파를 제어하는 것은 필수적입니다.
이 글에서 다룬 event.stopPropagation(), 캡처링 옵션 기법을 활용하면 더욱 직관적이고 예측 가능한 사용자 인터페이스를 구축할 수 있습니다.
참고 자료
- https://ko.javascript.info/bubbling-and-capturing
- MDN - stopPropagation