개발하는SM

[React] State Update Scheduling & 일괄 업데이트 본문

Web/Front-End

[React] State Update Scheduling & 일괄 업데이트

개발하는SM 2023. 4. 6. 22:45

서론

아래 코드에서 버튼을 눌렀을 때 <div> 에 찍히는 count 값은 왜 2이며 콘솔에 찍히는 count 값은 왜 1일까?

setCount(count+1) 을 3번 호출했으니 둘 다 4가 찍혀야 하는거 아닌가?

리액트에서 상태 갱신을 어떤 식으로 진행하며, 컴포넌트 재평가는 언제 일어나는지 알아보자.

setCount 연속 3번 호출
결과값


React State Update Scheduling

리액트는 상태 갱신을 어떻게 할까?

useState 훅에서 리턴되는 set 함수를 호출했을 때 즉각적으로 상태값이 변경되지는 않는다.

상태 업데이트를 "스케줄링" 하게 된다.

또한, 함수 호출 시 '리액트에서 관리하는 상태값'을 먼저 변경하며 우리 코드에 있는 상태값을 변경하지는 않는다.

우리 코드에 있는 상태값은 컴포넌트가 재실행되면서 '리액트에서 관리하는 상태값' 으로 변경되게 된다.

 

아래 그림의 예시를 통해 알아보자.

MyProduct 라는 컴포넌트가 있고, 해당 컴포넌트 내부에는 NewProduct 라는 State 가 있다. 

해당 State 의 초기값은 'DVD' 이다.

const [newProduct, setNewProduct] = useState('DVD');

MyProduct 컴포넌트 내부에서 setNewProduct('Book') 을 호출하면, 즉각적으로 우리 코드에 있는 상태값이 변경되지는 않는다.

대신, React 에 newProduct의 상태를 'Book' 으로 업데이트하라고 스케줄링을 하게 된다.

React 에서는 새로운 상태값 ( 'Book' ) 이 기존 상태값 ( 'DVD' ) 와 다른 것을 확인하고 상태값을 Update 한 후에 MyProduct 컴포넌트를 재실행한다.

컴포넌트가 재실행되면, 리액트에서 업데이트된 상태값이 우리 코드에 있는 상태값에 반영된다.

즉, 서론에서 setCount(count + 1) 이 호출된 뒤에도 콘솔에 count 값이 1로 찍힌 이유는,

setCount 를 통해 상태값 변경 스케줄링이 된 이후 컴포넌트의 재실행이 일어나기 이전에 콘솔에 값을 찍어주었기 때문이다.


상태값 일괄 업데이트 ( Batch Update )

위에서 알아본 바에 따르면, 상태값 변경 함수는 크게 2가지 일을 처리한다.

1. 상태를 변경

2. 함수 컴포넌트를 재실행

그런데, 상태값 변경 함수를 호출할 때마다 함수 컴포넌트를 재실행하는 것은 문제가 될 수 있다.

위의 예시에서와 같이 setCount() 함수를 연속으로 3번 호출하는데, 각 라인마다 컴포넌트를 재실행하는 것은 비효율적이며 어떤 식으로 동작할지 예측하기도 어렵다.

 

따라서 리액트에서는 하나의 함수가 처음부터 끝까지 어떠한 콜백이나 프로미스 없이 수행된다면, 이 함수 내에서 발생하는 모든 상태 갱신 작업을 일괄로 처리한다.

위에서 Add Count 버튼을 눌렀을 때 <div> 내의 Count 값이 4가 아니라 2가 된 원인도 이 일괄 업데이트 때문이다.

리액트에서 가지고 있는 count 상태값이 1인 상태에서 count + 1 업데이트가 이루어졌기 때문이다.

 

이러한 현상을 해결하기 위해 상태 변경 함수에 "콜백 함수"를 전달하여 해결할 수 있다.

콜백 함수에는 언제나 최신 값이 인수로 전달된다는 것이 보장된다.

콜백 함수를 전달하는 로직으로 수정하면 아래와 같다.

정상적으로 4가 찍히는 것을 확인할 수 있으며, 컴포넌트가 재실행된 이후 코드 안의 count 값이 4로 찍히는 것도 확인할 수 있다.

 


정리

리액트에서 상태값 변경 함수가 호출되었을 때 상태 업데이트가 "스케줄링" 된다.

이 상태값 변경 함수는 아래 2가지 일을 수행한다.

1. 리액트에서 관리하는 상태값 업데이트

2. 이전 상태값과 새로운 상태값이 다를 경우 함수 컴포넌트 재실행 ( 이 때 코드 내의 상태값이 변경됨 )

 

리액트에서는 하나의 함수가 처음부터 끝까지 어떠한 콜백이나 프로미스 없이 수행된다면,

이 함수 내에서 발생하는 모든 상태 갱신 작업을 일괄로 처리한다.

 

컴포넌트가 리랜더링 되는 시점과 상태 변경이 예약되는 시점의 차이를 아는 것은 중요함.

 


참고

https://velog.io/@kim98111/State-Update