[공식문서 톺아보기] batching / setState는 비동기인가요?

    batching(일괄처리)란?

    • React는 state 업데이트 하기 전에 이벤트 핸들러의 모든 코드가 실행될 때까지 기다린다.
      • 이 말의 의미는 React는 상태 변화를 비동기적으로 관리한다는 의미이다.
    • 그렇기 때문에 리렌더링은 모든 state 업데이트 함수 호출이 완료된 이후에만 일어난다. ⇒ batching
      • ⇒ 공식문서에선 음식점에서 주문 받는 웨이터를 예로 들고 있다. 웨이터는 한 가지의 요리만 듣고 주문을 넣는 것이 아니라 모든 주문을 받고 혹은 테이블에 있는 다른 사람의 주문을 받고 주문을 넣으러 간다
      • ⇒ 왜? 너무 많은 리렌더링을 하지 않아도 된다. 또 일부 변수만 업데이트된 반쯤 완성된 렌더링을 하지 않는다.

    React에서 batching을 사용하는 이유?

    • 렌더링 횟수를 줄여 성능을 향상시킨다.
    • 불필요한 렌더링을 방지한다.
    • 렌더링을 더 예측 가능하게 만든다.

    React가 여러 state 업데이트를 처리하는 방법

    import { useState } from 'react';
    
    export default function Counter() {
      const [number, setNumber] = useState(0);
    
      return (
        <>
          <h1>{number}</h1>
          <button onClick={() => {
            setNumber(number + 5);
            setNumber(n => n + 1);
            // React는 끝에서 딱 한 번 리렌더링을 한다. => batching
          }}>Increase the number</button>
        </>
      )
    }
    • setNumber(number + 5)
      • number는 0이므로 React는 큐에 number이 5로 업데이트 하는 것을 추가한다.
    • setNumber(n => n + 1);
      • React는 업데이터 함수를 큐에 추가한다.
      • n=5이고, return값이 5 +1 = 6이다.
    • React는 6을 최종 결과로 저장하고 useState에서 반환한다.

    Automatic batching

    React18에 추가된 개념으로 기본적으로 더 많은 일괄 처리를 수행하여 성능을 향상한다.

    React 18 이전에선 React 이벤트 핸들러 내에서만 업데이트를 일괄 처리했다. 이후 Automatic batching은 promise, setTimeout, 기본 이벤트 핸들러 또는 기타 이벤트 내부의 업데이트도 React 이벤트 내부의 업데트와 동일한 방식으로 일괄 처리된다.

     

    // React 18 이전
    setTimeout(() => {
      setCount(c => c + 1); // 렌더링
      setFlag(f => !f); // 렌더링
    }, 1000);
    
    // React 18 Automatic batching 이후
    setTimeout(() => {
      setCount(c => c + 1);
      setFlag(f => !f);
      // 리렌더링은 한 번만 이뤄진다. => batching
    }, 1000);

    만약 동기적으로 처리하고 싶다면? flushSync

    비동기적인 코드를 강제적으로 동기적으로 만들고 리렌더링을 강제로 하도록 한다. 이렇게 하면 DOM이 즉시 업데이트가 된다.

    하지만 React 공식문서에선 flushSync 사용이 앱 성능을 크게 저하 시킬 수 있고 최후의 수단으로만 사용하라고 경고하고 있다.


    참고 자료

    https://react-ko.dev/reference/react-dom/flushSync

    https://react-ko.dev/blog/2022/03/08/react-18-upgrade-guide#automatic-batching

    https://react.dev/learn/queueing-a-series-of-state-updates

    댓글