서론
React 18 에서는 Automatic Batching
이라는 기능이 추가되었다. 이 기능은 이전 버전의 Batching
보다 향상된 성능을 자랑한다.
본고에서는 기본적으로 Batching
이란 무엇인지, 그리고 이 기능을 사용하여 어떠한 효과를 가져오는지 실제 예시를 통해 알아보도록 하겠다.
본론
상태 변경과 렌더링: React의 핵심
React는 선언적
UI 라이브러리로, 우리가 어떤 화면을 보여줘야 하는지만 명시하면, React가 상태의 변경과 UI의 렌더링을 어떻게 처리할지 알아서 해준다.
예를 들어, setState
함수를 사용해서 상태를 변경하면, React는 그 상태에 맞춰 UI를 재렌더링
해 준다.
그런데, 상태가 여러 번 변경되면 어떻게 될까? 모든 상태 변경마다 UI를 재렌더링한다면, 불필요하게 많은 렌더링이 발생하게 될 것이다.
이런 경우에 React는 Batching
이라는 기능을 통해 여러 상태 변경을 한 번에 처리한다.
Batching 이란?
Batching
이란 React
에서 state
의 변화가 일어날 때, render
함수가 여러번 호출되는 것을 방지하기 위해
state
의 변화가 일어난 후, render
함수를 한번만 호출하는 것을 말한다. 이를 통해 불필요한 render
함수의 호출을 방지하여
렌더링 성능을 향상시킬 수 있다.
조금 더 풀어서 말해보자면, Batching
은 여러 개의 작업을 한 번에 묶는 것을 말한다.
예를 들어, 사무실에서 문서를 프린트할 때, 문서 한 장, 한 장을 따로따로 프린트하는 대신에 여러 문서를 한 번에 프린트하는 것과 비슷하다.
React에서도 이와 비슷한 원리로 동작하는데, 여러 개의 상태 변경을 한 번에 묶어서
처리한다는 점이다.
Batching 예시
import { useState } from 'react';
const App = () => {
const [count, setCount] = useState(0);
const onClick = () => {
setCount(count + 1); // re-renderering 이 일어나지 않는다.
setCount(count + 1); // re-renderering 이 일어나지 않는다.
// 마지막에 re-rendering 이 발생한다. (batching).
};
return (
<div>
<button onClick={onClick}>Click</button>
<p>{count}</p>
</div>
);
};
위 예시 코드를 주석을 신경쓰지 않고 원초적으로 보자면, onClick
함수가 실행되면 setCount
가 동기적
으로 실행되어, 기존
React Component 는 상태가 변경되면 re-rendering 이 일어난다.
말에 따라 총 2번의 re-rendering
이 발생할 것이라 생각할 수 있다.
하지만, 첫번째로 useState
훅의 setCount
함수는 동기적
으로 실행되지 않는다.
두밴쩌로 React 의 Batching 에 의해 onClick
함수 내의 두번의 setCount 로 인해 상태가 각기 변경되더라도, 마지막에 한번의 re-rendering
이 일어난다.
React 18 이전까지는, batched updates 오로지 React event handlers 내부에서만 작동했다. promises, setTimeout, native event handlers 에서는 batching이 일어나지 않았다.
Automatic Batching 이란?
Automatic Batching
은 React 18
에서 새롭게 추가된 기능으로서 Batching
을 자동으로 처리해주는 기능이다.
이전 Batching
과 다르게, 어디에서 상태가 변경되던지 상관없이 Batching
이 일어난다.
promises, setTimeout, native event handlers 등에서도 모두 Batching
이 일어난다.
Batching 을 피하고 싶다면?
하지만, 명시적으로 Batching 이 동작하길 원하지 않고, 매 상태변화 마다 DOM update 가 일어나야 하는 상황 또한 존재할 수 있다.
해당 케이스에서는 ReactDOM.flushSync()
를 사용하여 명시적으로 Batching 을 피할 수 있다.
import { useState } from 'react';
import { flushSync } from 'react-dom';
const App = () => {
const [count, setCount] = useState(0);
const onClick = () => {
flushSync(() => {
setCount(count + 1);
});
// re-renderering 이 일어난다.
flushSync(() => {
setCount(count + 1);
});
// re-renderering 이 일어난다.
};
return (
<div>
<button onClick={onClick}>Click</button>
<p>{count}</p>
</div>
);
};
결론
React의 Batching은 상태 변경을 최적화하고 렌더링 성능을 향상시키는 중요한 기능이다. 이를 이해하고 활용하면, 더욱 효율적인 React 애플리케이션을 만들 수 있을 것이다.