
트리 구조
DOM과 JavaScript의 관계

addEventListener의 세 번째 인자를 true로 설정하여 캡처링 이벤트 감지element.addEventListener("click", handler, true);
event.stopPropagation()으로 버블링 중단 가능이벤트 전파는 HTML의 계층 구조를 따라 진행됩니다.
<div class="grandparent">
<div class="parent">
<button class="child">클릭하세요</button>
</div>
</div>
// 각 요소에 이벤트 리스너 추가
const grandparent = document.querySelector(".grandparent");
const parent = document.querySelector(".parent");
const child = document.querySelector(".child");
// 캡처링 단계 이벤트 리스너
grandparent.addEventListener(
"click",
(e) => {
console.log("캡처링 - Grandparent");
},
true
);
parent.addEventListener(
"click",
(e) => {
console.log("캡처링 - Parent");
},
true
);
child.addEventListener(
"click",
(e) => {
console.log("캡처링 - Child");
},
true
);
// 버블링 단계 이벤트 리스너
grandparent.addEventListener("click", (e) => {
console.log("버블링 - Grandparent");
});
parent.addEventListener("click", (e) => {
console.log("버블링 - Parent");
});
child.addEventListener("click", (e) => {
console.log("버블링 - Child");
});
버튼 클릭 시 콘솔 출력 순서:
캡처링 - Grandparent
캡처링 - Parent
캡처링 - Child
버블링 - Child
버블링 - Parent
버블링 - Grandparent
실제 활용 예시:
// 이벤트 위임(Event Delegation) 패턴
document.querySelector("ul").addEventListener("click", function (e) {
if (e.target.tagName === "LI") {
// li 요소가 클릭되었을 때만 처리
console.log("리스트 아이템 클릭:", e.target.textContent);
}
});
// 1. 상태 관리 변수 정의
let secretNumber = Math.trunc(Math.random() * 20) + 1;
let score = 20;
let highscore = 0;
// 2. DOM 요소 선택 - 모든 필요한 요소 선택
const numberEl = document.querySelector(".number");
const guessEl = document.querySelector(".guess");
const messageEl = document.querySelector(".message");
const scoreEl = document.querySelector(".score");
const highscoreEl = document.querySelector(".highscore");
// 3. 메시지 표시 함수 추가 (코드 재사용성 향상)
const displayMessage = function (message) {
messageEl.textContent = message;
};
// 4. 클릭 이벤트 핸들러 구현
document.querySelector(".check").addEventListener("click", function () {
const guess = Number(guessEl.value);
// 가이드라인의 게임 로직을 실제 구현
// 4.1 입력값 검증
if (!guess) {
displayMessage("⛔ 숫자를 입력하세요!");
}
// 4.2 정답 확인
else if (guess === secretNumber) {
displayMessage("🎉 정답입니다!");
numberEl.textContent = secretNumber;
document.body.style.backgroundColor = "#60b347";
numberEl.style.width = "30rem";
// 최고 점수 업데이트
if (score > highscore) {
highscore = score;
highscoreEl.textContent = highscore;
}
}
// 4.3 오답 처리
else if (guess !== secretNumber) {
if (score > 1) {
displayMessage(
guess > secretNumber ? "📈 너무 높아요!" : "📉 너무 낮아요!"
);
score--;
scoreEl.textContent = score;
} else {
displayMessage("💥 게임 오버!");
scoreEl.textContent = 0;
}
}
});