Tech/ReactJS

비동기적으로 동작하지만 비동기 함수는 아닌 setState

닝닝깅 2024. 4. 13. 20:24

🔎 비동기적으로 동작하는 setState

setState로 상태 업데이트 후 예상처럼 값이 나오지 않는 경험을 여러번 했었다. 이유를 찾아보니 호출한 직후 상태가 바로 업데이트 되지 않을 수 있어 상태 업데이트 후 바로 상태값을 확인할 때 예상한 값이 나오지 않을 수 있다는 것이었다.

 

아래와 같은 방법을 통해 이 문제를 해결했었다.

1) useEffect 훅을 사용하여 상태 변경 후에 다음 로직을 실행하도록 설계한다.

useEffect(() => {
    console.log(value); 
}, [value])

2) 이전 상태에 의존할 경우 함수형 업데이트를 통하여 처리한다.

 const increment = () => {
    setCount(prevCount => prevCount + 1);
};

 

🔎 비동기 함수는 아닌 setState

setState의 비동기적 동작의 이유는 setState가 비동기 함수이기 때문이 아닐까 생각했다.

하지만 전혀 아니었다는 점..~~~~

 

결론부터 말해보자면

1. setState은 동기함수이다. 반환값이 프로미스가 아닌 것을 확인할 수 있다.

2. setState의 호출은 비동기적으로 일어나기 때문에 상태의 업데이트 결과가 즉각적으로 다음 코드라인에 반영되지 않는다.

 

이는 리액트의 리렌더링과 연관이 있다.

리액트는 가상돔을 사용해서 리렌더링을 진행한다. 컴포넌트의 상태나 속성이 변경되면 렌더링 함수가 호출되고, 렌더링 함수에 의해 가상돔이 업데이트 된다. 이후에 가상돔과 실제돔을 비교해 실제돔을 업데이트 한다. 

상태 업데이트 직후 콘솔을 찍는다고 하더라도 렌더링 시점에 참조하는 상태는 변경되지 않았기 때문에 비동기 함수의 실행처럼 보이게 된다.

 

그렇다면 리렌더링은 왜 비동기적으로 작동할까?

리액트의 실제돔에 가상돔의 변경된 부분을 반영하는 과정은 단계적으로 진행되는데, 가상돔 트리를 순회하면서 변경된 부분을 찾는 render phase와 실제돔에 변경사항을 반영하는 commit phase 두 단계로 진행된다.

만약, 이 단계적 진행이 동기적으로 진행된다면 메인 스레드가 차단되거나 응답지연이 발생해서 렌더링 과정이 지연된다. 이는 곧 사용자 경험을 저해하는 요소가 될 수 있다.

 

 


참고

https://velog.io/@jay/setStateisnotasync