타겟
이벤트가 실제로 발생한 요소, 즉 사용자가 직접 상호작용한 요소입니다.
이벤트 전파에서의 위치
이벤트 전파 3단계:
① 캡처링 (Capturing) window → 타겟으로 내려감
② 타겟 (Target) 실제 이벤트가 발생한 요소 ← 여기
③ 버블링 (Bubbling) 타겟 → window로 올라감
캡처링 버블링
window ────┼───────────────────────┼────
│ ▲
html ──────┼───────────────────────┼────
│ │
body ──────┼───────────────────────┼────
│ │
div ───────┼───────────────────────┼────
│ │
▼ │
button ─────────── 타겟 ────────────┘
↑
사용자가 실제로 클릭한 요소
타겟 확인 방법
<div id="parent">
<button id="child">클릭</button>
</div>
parent.addEventListener("click", (e) => {
console.log("target:", e.target); // 실제 클릭한 요소
console.log("currentTarget:", e.currentTarget); // 리스너가 붙은 요소
});
버튼 클릭 시:
target: <button id="child"> ← 실제 클릭한 요소
currentTarget: <div id="parent"> ← 리스너가 붙은 요소
target vs currentTarget
| 속성 | 의미 | 버블링 중 변화 |
|---|---|---|
| e.target | 이벤트가 실제 발생한 요소 | 변하지 않음 |
| e.currentTarget | 현재 핸들러가 실행 중인 요소 | 버블링마다 바뀜 |
grandparent.addEventListener("click", (e) => {
console.log("grandparent에서:");
console.log(" target:", e.target.id); // child (항상)
console.log(" currentTarget:", e.currentTarget.id); // grandparent
});
parent.addEventListener("click", (e) => {
console.log("parent에서:");
console.log(" target:", e.target.id); // child (항상)
console.log(" currentTarget:", e.currentTarget.id); // parent
});
child.addEventListener("click", (e) => {
console.log("child에서:");
console.log(" target:", e.target.id); // child (항상)
console.log(" currentTarget:", e.currentTarget.id); // child
});
버튼 클릭 시 출력:
child에서:
target: child
currentTarget: child
parent에서:
target: child ← 여전히 child (안 바뀜)
currentTarget: parent ← 현재 핸들러 위치
grandparent에서:
target: child ← 여전히 child (안 바뀜)
currentTarget: grandparent
버블링 흐름:
child (target = child, currentTarget = child)
│
▼
parent (target = child, currentTarget = parent)
│
▼
grandparent (target = child, currentTarget = grandparent)
→ target은 항상 처음 클릭한 요소
→ currentTarget은 현재 실행 중인 핸들러의 요소
타겟 단계의 특징
타겟 단계에서는 캡처링과 버블링 구분이 없습니다.
// 같은 요소에 캡처링과 버블링 둘 다 등록
btn.addEventListener("click", () => console.log("캡처"), true);
btn.addEventListener("click", () => console.log("버블"), false);
버튼 클릭 시 (타겟 단계):
캡처
버블
→ 타겟 요소에서는 등록 순서대로 실행
→ 캡처/버블 구분 없이 순서만 중요
// 등록 순서를 바꾸면
btn.addEventListener("click", () => console.log("버블"), false);
btn.addEventListener("click", () => console.log("캡처"), true);
출력:
버블
캡처
→ 타겟에서는 등록 순서대로 실행됨
타겟 활용 — 이벤트 위임
<ul id="list">
<li data-id="1">항목 1</li>
<li data-id="2">항목 2</li>
<li data-id="3">항목 3</li>
</ul>
// 부모에 리스너 하나만 등록
list.addEventListener("click", (e) => {
// target으로 실제 클릭한 요소 확인
if (e.target.tagName === "LI") {
const id = e.target.dataset.id;
console.log(`항목 ${id} 클릭`);
}
});
항목 2 클릭 시:
e.target = <li data-id="2">항목 2</li> ← 실제 클릭한 li
e.currentTarget = <ul id="list"> ← 리스너가 붙은 ul
→ target을 통해 어떤 li를 클릭했는지 알 수 있음
중첩 요소에서의 타겟
<button id="btn">
<span class="icon"></span>
<span class="text">알림</span>
</button>
btn.addEventListener("click", (e) => {
console.log("target:", e.target);
console.log("currentTarget:", e.currentTarget);
});
아이콘() 클릭 시:
target: <span class="icon"> ← 실제 클릭한 span
currentTarget: <button id="btn"> ← 리스너가 붙은 button
텍스트(알림) 클릭 시:
target: <span class="text"> ← 실제 클릭한 span
currentTarget: <button id="btn"> ← 리스너가 붙은 button
버튼 여백 클릭 시:
target: <button id="btn"> ← 실제 클릭한 button
currentTarget: <button id="btn"> ← 같음
target을 활용한 조건 처리
btn.addEventListener("click", (e) => {
// 특정 자식 요소 클릭 시 다른 동작
if (e.target.classList.contains("icon")) {
console.log("아이콘 클릭");
} else if (e.target.classList.contains("text")) {
console.log("텍스트 클릭");
}
// 버튼 전체 동작
console.log("버튼 클릭됨");
});
closest()와 함께 사용
<ul id="list">
<li data-id="1">
<span class="title">제목</span>
<button class="delete">삭제</button>
</li>
</ul>
list.addEventListener("click", (e) => {
// 삭제 버튼 클릭 시
if (e.target.classList.contains("delete")) {
const li = e.target.closest("li"); // 가장 가까운 li 찾기
const id = li.dataset.id;
console.log(`항목 ${id} 삭제`);
}
});
삭제 버튼 클릭 시:
e.target = <button class="delete">
e.target.closest("li") = <li data-id="1"> ← 부모 li를 찾음
→ target에서 시작해서 원하는 부모 요소를 찾을 수 있음
핵심 정리
타겟(target)은 이벤트가 실제로 발생한 요소입니다. e.target은 버블링 과정에서도 변하지 않아 "어디서 이벤트가 시작됐는지"를 항상 알 수 있고, e.currentTarget은 "현재 어떤 요소의 핸들러가 실행 중인지"를 나타냅니다. 이벤트 위임 패턴에서 e.target을 통해 실제 클릭한 자식 요소를 식별하고, closest()와 함께 사용하면 원하는 부모 요소까지 찾을 수 있습니다.