개인의 기록
  • 소개
  • 프로젝트
  • 글
  • 링크

© 2026 newgirok

← 글 목록

Event Handling — React에서 사용자 이벤트를 처리하는 방식

2026년 4월 30일
React이벤트SyntheticEvent

웹 애플리케이션에서 사용자 인터랙션은 이벤트를 통해 처리됩니다. React는 브라우저 네이티브 이벤트를 그대로 사용하지 않고 자체적인 합성 이벤트 시스템을 제공합니다. 이 시스템 덕분에 브라우저 간 동작 차이를 신경 쓰지 않고 일관된 방식으로 이벤트를 다룰 수 있습니다.

합성 이벤트(SyntheticEvent)

React의 모든 이벤트 핸들러는 브라우저 네이티브 이벤트 객체 대신 SyntheticEvent 객체를 받습니다.

SyntheticEvent: React가 브라우저 네이티브 이벤트를 감싸 만든 래퍼 객체. W3C 스펙을 따르며 모든 브라우저에서 동일하게 동작함.

SyntheticEvent는 브라우저 네이티브 이벤트와 동일한 인터페이스(target, currentTarget, type 등)를 갖추고 있어 기존 이벤트 처리 방식과 거의 동일하게 사용할 수 있습니다.

function Button() {
  const handleClick = (event) => {
    console.log(event.type);   // "click"
    console.log(event.target); // 클릭된 DOM 요소
  };

  return <button onClick={handleClick}>클릭</button>;
}

HTML과 달리 React의 이벤트 핸들러 이름은 camelCase를 사용합니다. onclick 대신 onClick, onsubmit 대신 onSubmit을 사용합니다. 또한 함수 참조를 전달해야 하며 문자열로 호출식을 작성하지 않습니다.

preventDefault

폼 제출, 링크 이동 등 브라우저의 기본 동작을 막을 때 preventDefault를 사용합니다. HTML에서는 이벤트 핸들러에서 false를 반환해도 기본 동작이 막혔지만, React에서는 반드시 event.preventDefault를 명시적으로 호출해야 합니다.

function Form() {
  const handleSubmit = (event) => {
    event.preventDefault(); // 페이지 새로고침 방지
    // 폼 데이터 처리 로직
  };

  return (
    <form onSubmit={handleSubmit}>
      <button type="submit">제출</button>
    </form>
  );
}

이벤트 버블링과 전파

DOM에서 이벤트는 발생한 요소에서 시작해 부모 요소 방향으로 전파됩니다. 이를 이벤트 버블링이라고 합니다.

function Parent() {
  return (
    <div onClick={() => console.log("부모")}>
      <button onClick={(e) => {
        e.stopPropagation(); // 부모로의 전파 차단
        console.log("자식");
      }}>
        클릭
      </button>
    </div>
  );
}

stopPropagation을 호출하지 않으면 버튼 클릭 시 "자식", "부모" 순으로 모두 출력됩니다. 전파를 막고 싶을 때만 stopPropagation을 사용하고, 무분별하게 사용하면 이벤트 위임 패턴을 방해할 수 있으므로 주의가 필요합니다.

이벤트 위임

이벤트 위임은 개별 자식 요소마다 이벤트 핸들러를 붙이지 않고, 공통 부모 요소 하나에 핸들러를 붙여 이벤트 버블링으로 모든 자식의 이벤트를 처리하는 패턴입니다.

React는 내부적으로 이벤트 위임을 활용합니다. React 17 이전에는 모든 이벤트를 document에 위임했고, React 17부터는 React 루트 DOM 컨테이너에 위임하는 방식으로 변경되었습니다. 덕분에 같은 페이지에 여러 React 앱이 존재해도 이벤트가 충돌하지 않습니다.

개발자가 직접 이벤트 위임 패턴을 활용할 때는 event.target으로 실제 이벤트 발생 요소를 확인합니다.

function List() {
  const handleClick = (event) => {
    if (event.target.tagName === "LI") {
      console.log("클릭된 항목:", event.target.textContent);
    }
  };

  return (
    <ul onClick={handleClick}>
      <li>항목 1</li>
      <li>항목 2</li>
      <li>항목 3</li>
    </ul>
  );
}

이 패턴은 항목 수가 많은 리스트에서 메모리를 절약하는 데 유용합니다.

← 이전 글State — 컴포넌트 내부의 변경 가능한 데이터
다음 글 →Hooks — 함수형 컴포넌트에서 상태와 생명주기를 사용하는 API