노트

React 상태 갱신

State Updates in React

프런트엔드#react · 연결된 개념 7개

쉽게 말하면

React 상태를 바꿀 땐 상자 안 물건만 바꿔 돌려주면 안 되고, 새 상자를 건네야 React가 알아채요. React는 '전과 같은 상자인가'만 비교해서, 같은 객체를 고쳐 넘기면 바뀐 줄 몰라 다시 그리지 않아요.

비유가 깨지는 곳 JPA 더티 체킹은 정반대로 같은 객체를 고치면 프레임워크가 찾아내요. 또 이전 값을 바탕으로 갱신할 땐 setCount(c => c + 1)처럼 함수를 넘겨야 오래된 값이 아닌 최신 값 기준으로 계산돼요.

React는 상태를 직접 고치지 않고 새 값을 setState로 넘겨야 다시 그린다. 이전 값과 Object.is로 비교하므로, 같은 객체를 고친 뒤 넘기면 바뀐 줄 모른다.

user.name = '새 이름'
setUser(user) // 같은 객체 → 다시 그리지 않음
setUser({ ...user, name: '새 이름' }) // 새 객체 → 다시 그림
  • JPA(Java Persistence API) 더티 체킹(Dirty Checking)은 정반대다. 같은 객체를 고치면 프레임워크가 스냅샷과 비교해 찾아낸다
  • 그래서 React 습관대로 id가 있는 새 엔티티 객체를 만들어 save()하면, 저장이 아니라 SELECT 후 merge가 일어난다

초기값 함수와 함수형 업데이트

  • 초기값 계산이 비싸면 값 대신 함수를 넘긴다. useState(() => expensive())는 첫 렌더에서만 함수를 실행한다. useState(expensive())라고 쓰면 버려질 값을 매 렌더마다 계산한다
  • 이전 값을 바탕으로 갱신할 때는 setCount(c => c + 1)처럼 함수를 넘긴다(함수형 업데이트, Updater Function). 한 이벤트에서 여러 번 갱신하거나 클로저에 오래된 값이 잡혀 있어도 최신 값 기준으로 계산된다
  • 상태가 여러 개 엮여 함께 바뀌면 useReducer, 렌더 중 계산할 수 있는 값을 상태로 두고 있다면 Effect가 필요 없는 경우를 본다

책: 7장. 영속성 컨텍스트라는 출석부

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 재조정(Reconciliation)

    재조정(Reconciliation)은 React가 이전 렌더의 엘리먼트 트리와 새 트리를 비교(Diffing)해, 실제 DOM(Document Object Model)에 필요한 최소한의 변경만 반영하는 과정이다. 두 트리를 완벽하게 비교하면 O(n³)이라, React는 두 가지 가정을 두어 O(n)으로 줄인다.

  • 상태 패턴

    객체의 행동이 현재 상태에 따라 달라질 때, 상태마다 별도 객체를 두고 현재 상태 객체에 행동을 맡기는 패턴. 상태별 조건문이 메서드마다 반복되는 문제를 푼다.

  • Redux 이후의 상태 관리 선택

    한때 React 앱의 기본값이던 Redux는 2025~2026년 기준으로 여러 선택지 중 하나가 됐다. 상태를 종류별로 나눠 각자에 맞는 도구를 고르는 방식이 자리 잡았기 때문이다.

  • useActionState와 폼 액션

    React 19에서는 <form action={함수}>에 함수를 바로 넘길 수 있고, useActionState가 그 액션의 대기 상태와 마지막 결과를 한 훅으로 관리한다. useState + onSubmit + 로딩 플래그로 짜던 패턴을 대체한다.

  • 내부 가변성과 메모이제이션

    내부 가변성(Interior Mutability)은 객체나 함수의 참조는 그대로인데 안에 숨은 상태가 바뀌는 성질이다. React의 메모이제이션은 "입력이 다른 참조인가"만 보기 때문에, 참조가 같으면 내용이 바뀌어도 바뀌지 않았다고 판단한다. React 공식 문서는 이를 "겉모습은 같은데 몰래 내용물을 바꾸는 상자"에 비유한다.

보기 옵션