React에서는 state를 업데이트 할 때 비동기적으로 동작한다.

React를 공부하던 중 useState를 쓸 때 주의해야 할 점에 대해서 배우게 되었다. 그것은 useState를 통해 만들어진 state를 변경하고자 할 때, 다음과 같이 코드를 작성하면 문제가 될 수 있다는 것이다.

const [isEditing, setIsEditing] = useState(false);

const handleEditClick = () => {
	setIsEditing(!isEditing); // 잘못된 코드 (리액트는 바로 state를 변경하지 않고 이를 스케쥴링한다.)
};

위의 코드가 잘못된 이유는 React는 state를 변경할 때 동기적으로 처리하지 않고 비동기적으로 처리한다. 위에서 setIsEditing은 비동기적으로 동작하고, 따라서 !isEditing이 예상되로 동작하지 않을 수 있다. 다음의 예시를 살펴보자.

const [isEditing, setIsEditing] = useState(false);

const handleEditClick = () => {
	setIsEditing(!isEditing);
	setIsEditing(!isEditing);
};

handleEditClick가 동작하면 isEditing의 상태는 어떻게 변할까? 초기값이 false이고 두 번 상태가 뒤집히니 그대로 false상태가 될 것이라고 예상할 수 있지만, 실제론 그렇지 않다. 조금 더 자세히 설명하면, setIsEditing는 비동기적으로 작동하기 때문에, 첫 번째 setIsEditing의 응답이 오기 전 두 번째 setIsEditing도 같이 스케쥴링 된다. 그렇게 되면 첫 번째와 두 번째 setIsEditing는 모두 false인 상태를 뒤집게되고, 둘 다 true의 상태를 return하게 된다. 따라서 위의 코드는 우리의 예상과는 다르게 isEditing=true가 되어버리는 것이다. 그림 이를 해결하기 위해선 어떻게 코드를 작성해야 할까?

const [isEditing, setIsEditing] = useState(false);

const handleEditClick = () => {
	setIsEditing((editing) => !editing); // 맞는 코드
	setIsEditing((editing) => !editing);
};

위의 코드처럼 작성하면 된다. 위와같이 작성하면 이전 상태값에 의존하여 새로운 상태값을 계산하게 되므로 React가 상태 업데이트를 정확하게 처리할 수 있으며, 비동기 문제를 방지할 수 있다. 이렇게 코드를 작성하면 handleEditClick이 실행되면 isEditing의 상태는 우리가 의도한 바에 맞게 false가 된다.

결론

오늘은 React에서 state를 업데이트할 때의 비동기적 특성과 이에 따라 발생할 수 있는 문제, 해결방법까지 포스팅하였다. 실제로 위의 예시코드와 같이 하나의 핸들러 안에서 같은 상태를 두 번 뒤집는 일은 일반적이지 않지만, 비동기적인 동작으로 인해 발생할 수 있는 문제의 예시를 보여준 것이라고 이해하면 좋을것 같다. 코드는 항상 예측 가능하도록 동작하게 작성해야 하고 이를 잘 보여줄 수 있는 예시라고 생각한다. 동기와 비동기에 대한 개념이 부족하다면, 이는 모든 개발자가 필수로 알고 있어야 하는 개념이니 공부를 하는것을 추천한다.

댓글남기기