본문 바로가기

웹 프론트엔드

[React] Batching을 활용한 렌더링 최적화

React 18(22.3.29)에서 Batching이 더욱 강화되었다.

Batching은 React에서 굉장히 중요한 개념이며, 최적화에 크게 기여하고 있다.

하지만 생각보다 Batching은 초보 리액트 개발자에게 널리 알려지지는 않은 것같다.

 

이번 포스팅에서 Batching이란 무엇이며, Batching을 알고나면 어떤 이점을 얻을 수 있는지 다루고자 한다.

배칭(Batching)이란?

batch는 일괄이라는 의미이다.

React에서는 어떤 의미로 쓰일까?

 

사례를 통해 알아보자.

 

아래 코드에서 button을 누르면 콘솔에 무엇이 찍힐까?

function App() {
  const [count, setCount] = useState(0);
  const handleClick = () => {
    setCount((count) => count + 1);
    setCount((count) => count + 1);
    setCount((count) => count + 1);
  };

  useEffect(() => {
    console.log("count", count);
  }, [count]);

  return <button onClick={handleClick}>+</button>;
}

1.

2.

자바스크립트에 기반하여 생각하면, 1번이 정답일 것이다.

setState가 3번 발생했고, count가 하나 증가할 때마다, 콘솔을 찍어줘야할 것 같다.

 

하지만, 실제로는 2번이 찍힌다.

 

이것이 batching이다.

감이 오는가?

 

3번의 상태변화가 3번의 렌더링을 발생시키지 않고, 한 번의 렌더링을 발생시켰다.

즉, 배칭이란 여러개의 state 업데이트를 하나의 리렌더링으로 묶는 것을 의미한다.

React는 왜 Batching을 설계했는가?

React 개발자 Dan Abramov가 다음과 같이 이야기했다.

 

"Batching is when React groups multiple state updates into a single re-render for better performance."

 

성능 최적화를 위해 배칭을 설계했다고 한다.

위 예시처럼 단 기간에 일어나는 상태변화를 매번 렌더링 시키지 않고, 일괄 처리함으로써 성능을 최적화한다.

 

레스토랑 직원이 하나의 주문을 받을 때마다 주방으로 가는 것은 비효율적이다.

수개의 주문이 동시에 들어온다면, 한번에 받아서 주방으로 향하는 것이 효율적일 것이다.

 

setState가 비동기로 동작하는 이유가 바로 여기에 있다.

일정 기간이 끝날 때까지 setState를 실행하지 않고 모아둔다.

Batching은 언제 발생하는가?

그렇다면 배칭은 어떤 단위로 발생하는지 궁금할 것이다.

 

React Event 단위로 배칭이 발생한다.

 

"This means that updates inside of timeouts, promises, native event handlers or any other event will batch the same way as updates inside of React events."

(React 18부터 Autumatic Batching이 등장했다. 이전보다 Batching이 더욱 강화되었다. 자세한 내용은 리액트 공식문서를 참고하길 바란다.)

Batching을 활용한 렌더링 최적화

배칭을 통해, 렌더링을 최적화해보았다.

아래 코드는, Validation을 수행하는 useInput이다.

처음에, onChange으로 값을 업데이트하는 로직과, Validation을 업데이트하는 관심사를 분리하기 위하여 useEffect을 사용했다.

하지만, 이 경우는 2번의 렌더링을 발생시킨다.

setValue, setValidation이 다른 리액트 이벤트에 기반하므로, 2번 렌더링한다.

function useInput() {
    const [value, setValue] = useState("");
    const [validation, setValidation] = useState(false);

    const onChange = (e) => {
      setValue(e.target.value);
    }

    // value 업데이트 되면, validation 업데이트
    useEffect(() => {
      setValidation(validate(value));
    }, [value]);

    const validate = (value) => {
        ...
    }

    return { value, validation, onChange }
}

배칭을 통해 1회만 렌더링 되도록 해보자.

function useInput() {
    const [value, setValue] = useState("");
    const [validation, setValidation] = useState(false);

    const onChange = (e) => {
      setValue(e.target.value);
      setValidation(validate(e.target.value)); // onChange 안으로 넣어주었다.
    }

    const validate = (value) => {
        ...
    }

    return { value, validation, onChange }
}

위와 같이 하나의 리액트 이벤트(onChange)에 두 가지 상태변화를 넣음으로써, 배칭을 가능하게 하고, 렌더링을 최적화하였다.

 

참고

 

Automatic batching for fewer renders in React 18 · Discussion #21 · reactwg/react-18

Overview React 18 adds out-of-the-box performance improvements by doing more batching by default, removing the need to manually batch updates in application or library code. This post will explain ...

github.com

 

React v18.0 – React Blog

React 18 is now available on npm! In our last post, we shared step-by-step instructions for upgrading your app to React 18. In this post, we’ll give an overview of what’s new in React 18, and what it means for the future. Our latest major version inclu

reactjs.org