🧩 junukim.dev

그리고

React Synthetic Event

React의 Synthetic Event에 대해 이야기합니다.

Synthetic Event

React에서 흔히 사용하는 onClick과 같은 이벤트는 무엇일까?


React.js에서 헨들링을 위해 사용하는 이벤트( onClick, onChange 등 )들은 브라우저의 이벤트가 아니다. 모두 React에서 제공하는 고유 이벤트 객체이다. 이를 Synthetic Event라고 부른다.

Synthetic Event???


Synthetic Event는 기본적으로 브라우저의 이벤트 객체로 이루어져 있지만, 추가로 Event Polling이라는 현상이 발생하게 된다. Event Polling은 또 무엇일까?

The SyntheticEvent is pooled. This means that the SyntheticEvent object will be reused and all properties will be nullified after the event callback has been invoked. This is for performance reasons. As such, you cannot access the event in an asynchronous way.

  • React docs

위 글은 React 공식 문서에 적혀있는 내용이고, 아래는 이를 해석한 내용이다.

React의 SyntheticEvent는 풀링된다. 이는 SyntheticEvent객체는 재사용되고, 이벤트 콜백이 호출된 후 모든 속성이 무효화됨을 의미한다. 이것은 성능상의 문제 때문이다. 따라서 비동기적으로 이벤트에 엑세스 할 수 없다.

  • React 독스

Synthetic Evnet들은 성능상의 문제 때문에 재사용 한다. 그리고 Event Polling은 이를 재사용 하기 때문에 발생하는 문제이다. *(여기서 재사용 이라고 함은 React에서 component를 재사용하는 것과 같은 이치이다.)* Synthetic Event를 실행하면 재사용을 하기위해 담겨있는 event객체를 null로 초기화 한다.

Event Polling으로 인한 변화는 다음과 같다.

  1. 성능상의 이슈로 발생하며 Synthetic Event객체가 초기화 된다.
  2. Synsthetic Event객체를 재사용하기 때문에 메모리 사용량이 적다.
  3. 해당 Synthetic Event가 실행될 때 한번만 발생한다.

Asynchronous

이러한 문제 때문에 Synthetic Event를 비동기와 함께 하면 Event Polling때문에 문제가 발생하게 된다. 하지만 이러한 문제를 해결하는 방법도 존재한다.

첫 번째는 SyntheticEvent에서 받아온 event객체를 복사한 뒤 비동기 작업이 끝난 이후 사용하는 방법이다. 이 방법은 성능상의 문제해결을 유지 한 체로 Event Pooling을 해결할 수 있다.

두 번째는 React에서 제공하는 event.persist()를 사용하는 방법이다. 이 방법은 성능상의 문제를 해결하지 않는다. 즉, 메모리상에 남아있도록 한다. 이러한 이유 때문에 성능상의 이득을 포기하고 싶지 않다면 사용하지 않는 것이 바람직하다.

Debounce

위의 방법들과 lodash의 debounce를 이용하여 Event Pooling문제를 깔끔하게 해결 할 수 있다. debounce를 이용하여 동기적인 처리를 해주고, event객체를 복사하여 사용하면 된다.

아래는 예시 코드이다.

import React, { useCallBack, useState } from "react";
import debounce from "lodash.debounce";

const Example = () => {
  const [name, setName] = useState("");

  const handleChange = (value) => setName(value);

  const debounceHandler = debounce(
    useCallBack(({ target: { value } }) => {
      handleChange(value);
    }, []),
    300
  );

  return (
    <input onChange={(event) => debounceHandler(event)} placeholder="이름..." />
  );
};

위 코드는 debounce를 이용해 0.3s 만큼 onChange Synthetic Event가 멈추고 난 후에 setName을 실행하여 name을 바꿔준다.

⇠ 이전 글 보러가기
첫 직장, 첫 월급 그리고 첫 FLEX 🤘🏻
다음 글 보러가기 ⇢
Typescript + React + Rollup으로 풀세트 Component Library만들기 😎