리액트 batching

오늘 코딩을 하다가 신기한 현상을 발견했다. 비동기 로직 안에 있는 useState의 set하는 함수가 batching이 안되는 것이다. 그래서 10개의 set 함수가 있으면 렌더링도 10번 발생하는 것을 확인했다. batching은 set 함수를 일정 주기별로 모아서 한 큐에서 한번에 처리하는 것으로 알고 있다.

const noBatching = async () => {
  const response = await asyncFunc();
  setA();
  setB();
  setC();
}

대충 이런 코드였다. 이 상황에서 a, b, c가 set되고, 한 번의 렌더링이 아닌 3번의 렌더링이 발생했다.

리액트는 기본적으로 batching을 한다고 알고 있었기 때문에 이해가 안갔지만 검색 끝에 이유를 알게 되었다. 예전에 어디선가 본 적이 있는 설명이였는데, 그땐 이해할 수 없었는데 지금은 이해가 간다.

결론부터 말하자면 리액트에서는 비동기 함수 안에 있는 set 함수를 처리할 때 batching을 하지 않는다. 그래서 setA, setB, setC는 각각 렌더링을 발생시키는 것이다. 실험을 해본 결과 setA, setB, setC는 모두 비동기는 맞다. 그리고 setA가 두 번 같은 값을 set하면 한 번만 렌더링이 발생한다.

즉, 렌더링이 발생하는 조건은 set 함수가 호출된 이후의 값과 이전 값이 다를때 발생한다.(당연한 얘기다. 하지만 batching을 하지 않는다고 해서 잠깐 당황했었다.)

하지만 위에서 setA, setB, setC가 한 번이 아닌 3번의 렌더링을 발생시키는 이유는 batching이 되지 않기 때문에 하나의 큐에 할당된 것이 아닌 각각이 큐에 할당되기 때문인 것 같다. 그냥 Promise를 3번 호출했다고 생각하면 될 것 같다.

이 결과로 알 수 있었던 것은 set 함수 안에 이전 값과 바뀐 값을 비교해서 렌더 함수를 호출하는 로직이 있는 것 같다는 것이다.(확실하진 않다.) 나중에 더 찾아보고 확실해지면 글을 써야겠다.

재밌는 경험이었고, 리액트 18부터는 비동기 함수 내에 있는 set 함수도 batching을 해준다고 한다. 얼른 리액트 18이 나왔으면 좋겠다.

참고 - Automatic batching for fewer renders in React 18

좋은 웹페이지 즐겨찾기