back

Posts

event.target과 event.currentTarget의 차이

2025-02-12

최근 면접에서 event.targetevent.currentTarget의 차이를 답변하는 질문이 있었습니다. 부끄럽게도 둘의 차이점을 반대로 얘기하는 대참사가 벌어졌죠. 그래서 저와 같은 분들이 없도록 포스트를 작성해보려고 합니다.

1. 이벤트 위임 (Event Delegation)

둘의 차이점을 알기 전에 먼저 JavaScript의 이벤트 위임을 이해해야 합니다.

이벤트 위임이란? 이벤트 리스너를 부모 요소에 등록하여, 하위 요소에서 발생하는 이벤트를 부모가 감지하고 처리하는 방법입니다.

이는 JavaScript의 버블링(Bubbling) 때문에 가능합니다. 버블링이란 자식 요소에서 발생하는 이벤트가 부모 요소로 전파되는 현상입니다. (그 반대는 캡처링입니다)

이벤트 위임은 주로 동적으로 생성되는 요소를 관리하기 위해 사용됩니다.

<ul id="parent">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
<button id="addItem">Add Item</button>

<script>
  const parent = document.getElementById("parent");
  const addItem = document.getElementById("addItem");

  // 이벤트 위임: 부모 요소에서 클릭 이벤트 감지
  parent.addEventListener("click", (event) => {
    if (event.target.tagName === "LI") {
      console.log(`Clicked: ${event.target.textContent}`);
    }
  });

  // 동적으로 리스트 추가
  addItem.addEventListener("click", () => {
    const newItem = document.createElement("li");
    newItem.textContent = `Item ${parent.children.length + 1}`;
    parent.appendChild(newItem);
  });
</script>

2. target과 currentTarget의 차이점

속성의미
target이벤트가 실제로 발생한 요소클릭된 <li>
currentTarget이벤트 리스너가 등록된 요소이벤트가 등록된 <ul>

위의 코드에서 <li>를 클릭하면:

  • event.target은 클릭된 <li> 요소입니다
  • event.currentTarget은 이벤트 리스너가 등록된 <ul> 요소입니다

3. React에서 왜 currentTarget을 사용할까?

React와 TypeScript를 사용할 때는 주로 currentTarget을 사용합니다. 그 이유는 무엇일까요?

이유 1: 타입 안정성

TypeScript에서 event.targetevent.currentTarget의 타입이 다릅니다.

<button onClick={handleClick}>
  <span>Click Me</span>
</button>;

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
  console.log(event.currentTarget); // HTMLButtonElement
  console.log(event.target); // EventTarget - 타입이 불명확
};

왜 이런 차이가 발생할까요?

  • currentTarget은 이벤트가 발생한 위치와 상관없이 타입이 항상 HTMLButtonElement입니다
  • target은 실제로 클릭된 요소를 가리키므로, <span>을 클릭하면 HTMLSpanElement가 됩니다
  • TypeScript는 정확히 어떤 자식 요소가 클릭될지 알 수 없으므로 타입이 불명확합니다

이유 2: 비동기 컨텍스트에서의 currentTarget

React 16까지는 SyntheticEvent 풀링(event pooling)이 있어서, 이벤트 핸들러 실행 후 event.target을 포함한 모든 속성이 null로 초기화됐습니다. 하지만 React 17에서 이벤트 풀링이 제거되면서 event.target은 비동기 컨텍스트에서도 안전하게 참조할 수 있습니다.

다만, event.currentTarget은 다른 이유로 여전히 주의가 필요합니다.

const handleClick = (event: React.MouseEvent) => {
  setTimeout(() => {
    console.log(event.target);        // React 17+ 에서 안전
    console.log(event.currentTarget); // null — 핸들러 종료 후 React가 리셋
  }, 1000);
};

currentTarget만 null이 될까요?

React는 이벤트 핸들러가 끝나는 시점에 currentTargetnull로 리셋합니다. 이벤트 전파가 완료된 시점에서 "현재 처리 중인 리스너"가 없어지기 때문입니다. 풀링과는 무관한 동작이며, React 17 이후에도 그대로 유지됩니다.

비동기에서 currentTarget이 필요하다면 미리 변수에 저장해야 합니다.

const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
  const currentTarget = event.currentTarget; // 핸들러 실행 중에 저장

  setTimeout(() => {
    console.log(currentTarget); // 안전
  }, 1000);
};

정리

항목event.targetevent.currentTarget
의미실제로 이벤트가 발생한 요소이벤트 리스너가 등록된 요소
TypeScript 타입불명확 (EventTarget)명확 (지정한 타입)
비동기 사용React 17+ 에서 안전핸들러 종료 후 null — 미리 저장 필요
추천 사용처이벤트 위임 시 실제 클릭된 요소 확인이벤트 핸들러 등록 요소 접근

이제 여러분도 면접에서 헷갈리지 않고, 확실하게 답변할 수 있을 것 같습니다!