[React] 왜 setState(prev => …)를 써야 할까? React 상태 업데이트의 비밀

박감자·2025년 9월 22일

React useState: prev를 쓸까, state를 그대로 가져올까?

리액트를 사용하다 보면 상태를 업데이트할 때 두 가지 방법을 자주 접한다.

// 1. 직접 상태를 이용하는 방법
setCount(count + 1);

// 2. 이전 상태(prev)를 이용하는 방법
setCount((prev) => prev + 1);

겉으로 보기에는 두 코드 모두 count 값을 1 증가시키는 것처럼 보이지만 리액트의 상태 업데이트 방식 때문에 이 두 가지 방법은 미묘한 차이를 가지고 있다.

1. 직접 상태를 사용하는 방법

setCount(count + 1);

이 방식은 단순히 현재 count 변수를 읽어서, 그 값에 1을 더해 새로운 상태를 설정.
하지만 리액트의 특징 중 하나가 상태 업데이트가 비동기적(asynchronous)이고, 이때문에 여러 개가 한 번에(batch) 처리될 수 있다

문제 상황

만약 이벤트 루프 내에서 여러 번 setCount(count + 1)을 호출한다면...?

setCount(count + 1);
setCount(count + 1);
setCount(count + 1);

개발자의 의도는 count가 3 증가하는 것일 거다.
그렇지만 실제로는 모든 호출이 동일한 초기 count 값을 기준으로 계산되어, 최종적으로는 단 1만 증가하게 되는 문제가 발생할 수 있다.

2. 이전 상태(prev)를 사용하는 방법

setCount((prev) => prev + 1);

이 방식은 setCount에 함수를 전달한다. 함수의 인자로는 항상 최신 상태(prev) 가 들어오기 때문에, 상태 업데이트가 비동기적이거나 여러 번 배치되더라도 안전하게 원하는 값으로 업데이트가 가능하다. 즉 아래의 예시에서

예시

setCount((prev) => prev + 1);
setCount((prev) => prev + 1);
setCount((prev) => prev + 1);

위 코드는 순차적으로 실행되어 count가 정확히 3 증가한다는 것!
결론은 상태를 기반으로 새로운 값을 계산해야 할 때는 prev 방식을 쓰는 것이 안정적 이라는 것이다.

어떤 방법을 써야 할까?

  • 현재 값으로 단순히 교체할 때
    → 직접 참조 (setState(value)) 방식을 사용해도 무방
    예: setIsOpen(true)

  • 이전 상태를 기반으로 새로운 값을 계산할 때
    → 반드시 prev 방식 (setState(prev => ...))을 쓰는 것이 안전
    예: 카운터 증가, 토글, 누적 값 처리

그래서 결론

React의 상태 업데이트는 동기적으로 즉시 반영되는 것이 아니라, 비동기적이고 배치 처리될 수 있다.

따라서 setState(count + 1) 방식은 간단하지만, 동시에 여러 번 호출될 경우 의도와 다른 결과가 나온다는 것. (버튼을 10번 동시에 눌러도 2가 될 수 있다ㅏㅏ)

반대로 setState(prev => prev + 1) 방식은 항상 최신 상태를 기준으로 동작하기 때문에, 여러 번의 상태 변경에도 안정적이다. (100번을 동시에 눌러도 문제 ㄴㄴ)

👉 결론: 이전 상태에 의존하는 연산이라면 반드시 prev를 사용하자!

마무리...

setState 정도는 이제 자신 있다고 생각했지만 난 여전히 무지했고 오늘 하나 더 알아간다.

참조

https://dev.to/harsh8088/avoiding-common-usestate-mistakes-in-react-3aao

profile
코딩하는 감자

0개의 댓글