React의 setState가 비동기 처리되는 이유

React, Batch Update

Posted by Seongkyun Yu on 2020-09-28
Estimated Reading Time 2 Minutes
Words 434 In Total
Viewed Times

React를 공부할 때 중요하게 배우는 개념 중 하나는 상태관리 입니다.

React는 상태를 바탕으로 View를 그리기 때문에 일반 변수로 사용하지 않고 setState로 상태를 할당한다는 것을 배우죠.

하지만 JavaScript를 공부할 때 처럼 console.log로 상태 변화를 확인하려 하면 이상한 점을 느끼게 됩니다.

그 이상함(console.log의 결과값이 이전 상태를 나타냄)은 setState가 비동기적으로 처리되기 때문인데 어째서 React는 상태 변화를 비동기적으로 관리하는지 정리해보겠습니다.



흔히 하는 실수

많이들 하는 실수인데, 상태를 처음 접하면 많이들 아래와 같은 코드로 변경된 상태를 확인하려 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, { useState } from "react";

function App() {
const [state, setState] = useState(1);

const upState = () => {
setState(state + 1);
console.log(state);
};

return (
<div className="App">
<button onClick={upState}>상태값 UP</button>
<p>상태값은 {state}</p>
</div>
);
}

export default App;

버튼을 누르면 변경한 상태값이 정확히 랜더링 됩니다.

하지만 이상하게도 console.log(state)값은 이전 상태값을 출력하죠.

이러한 문제 떄문에 setState 이후 바로 상태값을 참조하여 다른 작업을 할 때 문제가 생기게 됩니다.

그리고 그 문제를 해결하기 위해서 react-thunk, react-saga등을 사용해 동기화 처리를 해줍니다.

그렇다면 왜 React는 상태값을 비동기적으로 처리하게 만들었을까요?



React batch update

리액트는 batch update를 16ms 단위로 진행합니다.

16ms 동안 변경된 상태 값들을 모아서 단 한번 리랜더링을 진행합니다.

이러한 행동은 웹 페이지 랜더링 횟수를 줄여 좀 더 빠른 속도로 동작하게끔 도와줍니다.

아래의 코드로 랜더링 횟수를 확인해 볼 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import React, { useEffect, useState } from "react";

function App() {
const [state1, setState1] = useState(1);
const [state2, setState2] = useState(1);
const [state3, setState3] = useState(1);
const [renderCount, setRenderCount] = useState(0);

const upState = () => {
setState1(state1 + 1);
setState2(state2 + 1);
setState3(state3 + 1);
};

useEffect(() => {
setRenderCount(renderCount + 1);
}, [state1, state2, state3]);

return (
<div className="App">
<button onClick={upState}>상태값 UP</button>
<p>상태값1 {state1}</p>
<p>상태값2 {state3}</p>
<p>상태값3 {state3}</p>
<p>랜더링 횟수 {renderCount}</p>
</div>
);
}

export default App;

코드를 실행하여 상태값 UP 버튼을 누르면 각각의 상태들을 1씩 올려줍니다.

상태값을 바꿀 때 마다 리랜더링을 한다면 랜더링 횟수는 늘어나야 하는데 버튼 한 번당 동일하게 1씩 올라갑니다.

따라서 React는 일정 시간동안 변화한 상태값들을 모아 한 번에 처리하는 것을 알 수 있습니다.



결론

React의 setState 등이 비동기적으로 작동하는 이유는 일정시간동안 변화하는 상태를 모아 한 번에 랜더링 하기 위해서입니다.



참고자료: https://medium.com/swlh/react-state-batch-update-b1b61bd28cd2


If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. If the images used in the blog infringe your copyright, please contact the author to delete them. Thank you !