의도: 버블링과 캡처링으로 이벤트를 제어할 수 있는지 확인하는 질문
팁: 이름에서 오는 뜻을 활용한다.
나의 답안
이벤트 버블링과 캡처링은 DOM에서 이벤트가 발생했을 때 처리되는 전파 방식을 설명하는 개념입니다.
DOM에서 이벤트는 특정 요소에서 발생하고, 해당 이벤트가 DOM 트리를 따라 전파되면서 처리됩니다.
이벤트 버블링은 이벤트가 발생한 요소에서 시작하여 부모 요소로, 그 부모의 부모 요소로, 최상위 요소까지 상향 전파되는 과정을 의미합니다.
이벤트는 특정 요소에서 발생하지만, 상위 요소로 전파되기 때문에 부모나 조상 요소에서도 이벤트를 처리할 수 있습니다.
이벤트 캡처링은 이벤트가 최상위 요소에서 시작하여 타깃 요소로 하향 전파되는 과정입니다.
기본적으로 DOM의 이벤트는 버블링 단계에서 실행됩니다.
캡처링 단계에서 이벤트를 처리하려면 addEventListener 메서드에서 세 번째 인자로 true를 전달하면 됩니다.
주어진 답안 (모범 답안)
이벤트 버블링과 캡처링은 모두 이벤트가 전파되는 방식을 뜻합니다.
다만 서로 그 방향이 다를 뿐입니다.
버블링부터 말씀드리자면, 버블링은 마치 거품이 수면으로 떠올라가듯이 이벤트가 전파되는 것입니다.
그래서 하위 요소에서 상위 요소로 이벤트가 전파되는 것을 버블링이라고 합니다.
반대로 캡처링은 포착한다고 생각하시면 됩니다.
마치 카메라가 내가 보는 시야의 일부분을 포착해서 담듯이 이벤트가 전파되는 겁니다.
그래서 캡처링은 상위 요소에서 하위 요소로 이벤트가 전파되는 것을 의미합니다.
이러한 특성을 잘 활용한다면 이벤트 위임을 구현할 수 있습니다.
이벤트 버블링과 캡처링은 DOM(Document Object Model)에서 이벤트가 발생했을 때 처리되는 전파 방식을 설명하는 개념이다.
DOM에서 이벤트는 특정 요소에서 발생하고, 해당 이벤트가 DOM 트리를 따라 전파되면서 처리된다.
이벤트 전파는 다음과 같은 3단계로 이루어진다.
캡처링 단계 (Capturing Phase)
이벤트가 최상위 요소(window 또는 document)에서 시작하여 이벤트가 발생한 타깃 요소(target)까지 위에서 아래로 내려가는 단계이다.
타깃 단계 (Target Phase)
이벤트가 발생한 요소에서 실행되는 단계이다. 이 단계에서는 캡처링과 버블링 방식에 관계없이 이벤트 핸들러가 실행된다.
버블링 단계 (Bubbling Phase)
이벤트가 타깃 요소에서 다시 상위 요소로 아래에서 위로 올라가는 단계이다.
정의
이벤트가 발생한 요소에서 시작하여 부모 요소로, 그 부모의 부모 요소로, 최상위 요소까지 상향 전파되는 과정
동작 방식
이벤트는 특정 요소에서 발생하지만, 상위 요소로 전파되기 때문에 부모나 조상 요소에서도 이벤트를 처리할 수 있다.
예제
HTML 구조
<div id="parent">
<button id="child">Click Me!</button>
</div>
JavaScript
document.getElementById("parent").addEventListener("click", () => {
console.log("Parent clicked!");
});
document.getElementById("child").addEventListener("click", () => {
console.log("Child clicked!");
});
실행 결과
1) 버튼(child)을 클릭하면 "Child clicked!"가 먼저 출력된다.
2) 이후 "Parent clicked!"가 출력된다.
→ 이벤트가 자식에서 부모로 전파된 결과이다.
정의
이벤트가 최상위 요소에서 시작하여 타깃 요소로 하향 전파되는 과정
동작 방식
기본적으로 DOM의 이벤트는 버블링 단계에서 실행된다.
하지만 캡처링 단계에서 이벤트를 처리하려면 addEventListener 메서드에서 세 번째 인자로 true를 전달해야 한다.
예제
HTML 구조
<div id="parent">
<button id="child">Click Me!</button>
</div>
JavaScript
document.getElementById("parent").addEventListener(
"click", () => {
console.log("Parent clicked!");
}, true // 캡처링 단계에서 실행
);
document.getElementById("child").addEventListener("click", () => {
console.log("Child clicked!");
});
실행 결과
1) 버튼(child)을 클릭하면 "Parent clicked!"가 먼저 출력된다. → 캡처링 단계에서 부모 요소의 이벤트가 실행된다.
2) 이후 "Child clicked!"가 출력된다.
| 특성 | 이벤트 버블링 | 이벤트 캡처링 |
|---|---|---|
| 전파 방향 | 타깃 요소 → 부모 요소(상향) | 최상위 요소 → 타깃 요소(하향) |
| 기본 동작 | 대부분의 브라우저는 기본적으로 버블링 단계에서 이벤트 처리 | 캡처링 단계에서 이벤트 처리는 명시적으로 설정 필요(true) |
| 사용 목적 | 타깃 이후의 상위 요소에서 이벤트 처리 필요 시 | 타깃 이전의 상위 요소에서 이벤트 처리 필요 시 |
이벤트 버블링과 캡처링을 제어하기 위해 아래의 메서드들을 사용할 수 있다.
event.stopPropagation()
이 메서드는 현재 이벤트의 전파를 중단한다.
버블링 단계에서 호출되면 상위 요소로 이벤트가 전파되지 않는다.
캡처링 단계에서 호출되면 하위 요소로 이벤트가 전파되지 않는다.
예제
document.getElementById("parent").addEventListener("click", () => {
console.log("Parent clicked!");
});
document.getElementById("child").addEventListener("click", (event) => {
console.log("Child clicked!");
event.stopPropagation(); // 부모 요소로 이벤트 전파 중단
});
실행 결과: "Child clicked!"만 출력된다.
event.stopImmediatePropagation()
이 메서드는 이벤트의 전파를 중단하고, 같은 요소에 등록된 다른 이벤트 핸들러의 실행도 중단한다.
예제
document.getElementById("child").addEventListener("click", () => {
console.log("First handler");
});
document.getElementById("child").addEventListener("click", (event) => {
console.log("Second handler");
event.stopImmediatePropagation(); // 이후 핸들러 실행 중단
});
document.getElementById("child").addEventListener("click", () => {
console.log("Third handler");
});
실행 결과: "Second handler"만 출력된다.
event.preventDefault()
이 메서드는 기본 동작을 막는다. (이벤트 전파와는 무관)
document.querySelector("a").addEventListener("click", (event) => {
event.preventDefault(); // 링크의 기본 동작 차단
console.log("Link clicked!");
});<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>document.getElementById("list").addEventListener("click", (event) => {
if (event.target.tagName === "LI") {
console.log(`Clicked: ${event.target.textContent}`);
}
}); 실행 결과: 클릭한 li 요소만 처리되며, 새로운 li 요소가 동적으로 추가되어도 이벤트가 잘 작동한다.캡처링을 활용한 부모 우선 처리
특정 상황에서 부모 요소의 이벤트가 먼저 실행되어야 할 경우, 캡처링을 활용할 수 있다.
<div id="parent" style="padding: 20px; background-color: lightblue;">
Parent
<button id="child" style="margin-top: 10px;">Child</button>
</div>
// 부모 요소에 캡처링 단계에서 이벤트 등록
document.getElementById("parent").addEventListener(
"click",
() => {
console.log("Parent clicked (Capturing phase)");
},
true // 캡처링 단계에서 실행
);
// 자식 요소에 버블링 단계에서 이벤트 등록
document.getElementById("child").addEventListener("click", () => {
console.log("Child clicked (Bubbling phase)");
});
실행 결과
child)을 클릭하면 콘솔에 다음 순서로 출력된다.Parent clicked (Capturing phase)
Child clicked (Bubbling phase)캡처링 단계에서만 부모 요소의 특정 동작 처리
부모 요소의 이벤트를 캡처링 단계에서만 실행하고, 이벤트가 자식으로 전달되지 않도록 설정할 수 있다.
<div id="parent" style="padding: 20px; background-color: lightblue;">
Parent
<button id="child" style="margin-top: 10px;">Child</button>
</div>
document.getElementById("parent").addEventListener(
"click",
(event) => {
console.log("Parent clicked (Capturing phase)");
event.stopPropagation(); // 이벤트가 자식으로 전파되지 않도록 설정
},
true // 캡처링 단계에서 실행
);
document.getElementById("child").addEventListener("click", () => {
console.log("Child clicked (Bubbling phase)");
});
실행 결과
child)을 클릭해도 자식 요소의 이벤트는 실행되지 않는다.Parent clicked (Capturing phase)