이벤트 전파 단계
- 캡처링 단계
- 이벤트가 최상위에서 시작해 타깃 요소로 내려갑니다.
- 이 단계에 등록된 핸들러는 캡처링 리스너라고 부릅니다.
- 타깃 단계
- 이벤트가 실제 발생한 요소(이벤트 타깃)에서 처리됩니다.
- 이때, 요소에 등록된 캡처링과 버블링 리스너 모두 실행됩니다.
- 버블링 단계
- 이벤트가 타깃에서 시작해 최상위로 다시 올라갑니다.
- 이때 등록된 버블링 리스너가 실행됩니다.
대부분의 경우 우리는 버블링 단계의 이벤트만 다루게 되지만, 특정 상황(예를 들어, 부모 요소에서 자식의 이벤트를 미리 가로채야 할 때)에는 캡처링 단계 리스너가 유용합니다.
이벤트 버블링: 기본 전파 방식
<form onclick="alert('폼 클릭됨')">FORM
<div onclick="alert('DIV 클릭됨')">DIV
<p onclick="alert('P 클릭됨')">여기를 클릭하세요</p>
</div>
</form>
<p> 요소를 클릭하면:
- 먼저 <p>의 onclick 핸들러가 실행되어 "P 클릭됨"을 표시.
- 이벤트가 <div>로 버블링되어 "DIV 클릭됨" 표시.
- 마지막으로 <form>에 도달해 "폼 클릭됨" 표시.
이 순서(p → div → form)는 이벤트가 DOM 트리를 따라 올라가는 과정을 보여주며, 물속 거품처럼 위로 올라가는 모습에서 버블링이라는 이름이 유래했습니다.
버블링 주요 특징
- click, mousedown, keyup 같은 대부분의 이벤트는 기본적으로 버블링.
- focus, blur 같은 이벤트는 버블링되지 않고 타겟 요소에만 작용.
- 버블링은 루트(document) 또는 일부 이벤트의 경우 window까지 진행.
이벤트 핸들러와 전파 객체
이벤트 핸들러 내부에서는 두 가지 중요한 프로퍼티에 접근할 수 있습니다:
- event.target: 실제 이벤트가 발생한 최안쪽 요소를 가리킵니다.
- event.currentTarget(or this): 현재 이벤트 핸들러가 부착된 요소를 가리킵니다.
예제: 이벤트 전파와 타깃 구분하기
<!DOCTYPE html>
<html>
<head>
<style>
.box {
padding: 20px;
border: 2px solid #3498db;
margin: 10px;
}
</style>
</head>
<body>
<div class="box" id="outer">
Outer Div
<div class="box" id="inner">
Inner Div
<button id="btn">Click Me</button>
</div>
</div>
<script>
// 캡처링 리스너 (capture: true)
document.getElementById("outer").addEventListener("click", function(event) {
console.log("캡처링 - Outer:", event.eventPhase, event.currentTarget.id, "타깃:", event.target.id);
}, true);
// 버블링 리스너 (기본, capture: false)
document.getElementById("outer").addEventListener("click", function(event) {
console.log("버블링 - Outer:", event.eventPhase, event.currentTarget.id, "타깃:", event.target.id);
});
document.getElementById("inner").addEventListener("click", function(event) {
console.log("Inner Div:", event.eventPhase, event.currentTarget.id, "타깃:", event.target.id);
});
document.getElementById("btn").addEventListener("click", function(event) {
console.log("Button:", event.eventPhase, event.currentTarget.id, "타깃:", event.target.id);
// event.stopPropagation(); // 이 줄을 주석 해제하면 상위 핸들러 실행 중단!
});
</script>
</body>
</html>
- 캡처링 단계: 가장 먼저 outer 요소의 캡처링 리스너가 실행되어 콘솔에 로그를 남깁니다.
- 타깃 단계: 버튼이 클릭되면서 btn의 핸들러가 실행되고, 동시에 inner와 outer 요소의 버블링 리스너도 실행됩니다.
- 전파 제어: 만약 btn 핸들러 내에서 event.stopPropagation()을 호출하면, 상위 요소로 이벤트가 버블링되지 않습니다.
이벤트 버블링 중단하기
상황에 따라 이벤트가 상위 요소로 전파되는 것을 막아야 할 때가 있습니다. 이때 event.stopPropagation() 또는 event.stopImmediatePropagation() 을 사용합니다.
- event.stopPropagation(): 동일 요소의 다른 핸들러는 실행됨
- event.stopImmediatePropagation(): 동일 요소의 다른 핸들러도 실행되지 않음
예제: 이벤트 전파 중단
<!DOCTYPE html>
<html>
<body>
<div id="container" style="padding: 20px; border: 2px solid green;">
<button id="stopBtn">Stop Propagation</button>
</div>
<script>
// container에 버블링 리스너 등록
document.getElementById("container").addEventListener("click", function() {
alert("컨테이너에서 이벤트가 감지되었습니다.");
});
// 버튼에 이벤트 리스너 등록
document.getElementById("stopBtn").addEventListener("click", function(event) {
alert("버튼 클릭됨. 버블링 중단!");
event.stopPropagation(); // 부모에게 전파되지 않음
});
</script>
</body>
</html>
'브라우저' 카테고리의 다른 글
이벤트 위임과 브라우저 기본 동작 제어 (0) | 2025.02.20 |
---|---|
이벤트 위임: 효율적인 이벤트 관리 (0) | 2025.02.20 |
브라우저 이벤트: 웹 상호작용의 핵심 (0) | 2025.02.20 |
브라우저에서 요소 좌표 다루기 (0) | 2025.02.20 |
브라우저 창과 스크롤 이해하기: 웹 레이아웃의 숨겨진 영역 (0) | 2025.02.20 |