타겟

이벤트가 실제로 발생한 요소, 즉 사용자가 직접 상호작용한 요소입니다.

이벤트 전파에서의 위치

이벤트 전파 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()와 함께 사용하면 원하는 부모 요소까지 찾을 수 있습니다.

CSLOG에서 보기