Skip to content

Latest commit

 

History

History
144 lines (113 loc) · 4.89 KB

2주차_류지예_공통.md

File metadata and controls

144 lines (113 loc) · 4.89 KB

setState의 업데이트 객체 탐구: React는 왜 이런 방식을 선택했을까?

0. 들어가며: React의 상태 관리 방식에 대한 의문

useStatesetState 호출이 단순히 값을 변경하는 대신 "업데이트 객체"를 생성하고 이를 큐에서 관리합니다.

  1. React는 왜 단순히 값을 변경하는 대신, 업데이트를 객체로 관리하는가?
  2. React는 이 객체들을 어떻게 처리하여 최종 상태를 결정하는가?

이 글에서는 React의 내부 구현을 살펴보며 이 의문들에 대한 답을 찾아보겠습니다.

1. React는 왜 업데이트를 객체로 관리할까?

1.1 업데이트 객체의 구조

React의 상태 업데이트는 단순한 값 대입이 아닌, 업데이트에 대한 모든 정보를 담은 객체로 만들어집니다.

React의 useState의 실제 구현인 dispatchSetStateInternal을 살펴봐 상태 업데이트가 어떻게 객체로 변환되는지 실제 코드를 통해 살펴보겠습니다.

ReactFiberHooks.js

function dispatchSetStateInternal<S, A>(
  fiber: Fiber,
  queue: UpdateQueue<S, A>,
  action: A,
  lane: Lane,
): boolean {
  const update: Update<S, A> = {
    lane,
    revertLane: NoLane,
    action,
    hasEagerState: false,
    eagerState: null,
    next: null,
  };
  // ...
}

1.2 업데이트 객체의 이점

이러한 객체 기반 접근의 주요 이점들을 살펴보겠습니다:

  1. 상태 업데이트의 추적

    const update = {
      action: newState,    // 의도된 변경사항
      next: null,          // 다음 업데이트와의 연결
    };
    • 모든 상태 변경을 추적할 수 있음
    • 필요한 경우 변경을 취소하거나 재시도 가능
  2. 우선순위 기반 처리

    const update = {
      lane: SyncLane,      // 우선순위 정보
      revertLane: NoLane   // 복구 정보
    };
    • 중요한 업데이트를 우선적으로 처리
    • 덜 중요한 업데이트는 나중으로 지연
  3. 최적화와 일관성

    const update = {
      hasEagerState: false,  // 즉시 처리 가능 여부
      eagerState: null       // 미리 계산된 상태
    };
    • 가능한 경우 상태를 미리 계산
    • 불필요한 재렌더링 방지

이러한 객체 기반 관리는 다음 섹션에서 볼 상태 업데이트 처리의 토대가 됩니다.

2. React는 어떻게 최종 상태를 결정할까?

2.1 업데이트 큐 관리

상태 업데이트는 단순히 발생하는 대로 처리되지 않고, 큐를 통해 체계적으로 관리됩니다.

ReactFiberHooks.js

function mountState<S>(initialState) {
  const hook = mountStateImpl(initialState);
  const queue = hook.queue;
  const dispatch = dispatchSetState.bind(
    null, 
    currentlyRenderingFiber, 
    queue
  );
  queue.dispatch = dispatch;
  return [hook.memoizedState, dispatch];
}
  • 각 상태마다 독립적인 업데이트 큐 유지
  • 업데이트의 순서와 우선순위 보장
  • 일괄 처리(batching)를 통한 성능 최적화

2.2 업데이트 최적화

React는 성능 최적화를 위해 가능한 경우 업데이트를 즉시 처리하려 시도합니다.

if (fiber.lanes === NoLanes &&
    (alternate === null || alternate.lanes === NoLanes)) {
  // 현재 진행 중인 다른 업데이트가 없다면
  const lastRenderedReducer = queue.lastRenderedReducer;
  const currentState = queue.lastRenderedState;
  const eagerState = lastRenderedReducer(currentState, action);

  update.hasEagerState = true;
  update.eagerState = eagerState;
  
  if (is(eagerState, currentState)) {
    // 상태가 실제로 변경되지 않았다면 업데이트 취소
    return false;
  }
}
  1. 다른 진행 중인 업데이트 확인
  2. 즉시 상태 계산 가능 여부 판단
  3. 불필요한 업데이트 조기 종료

2.3 최종 상태 결정

업데이트의 종류에 따라 서로 다른 처리 전략을 사용합니다.

// 1. 직접 값 설정 - 즉시 계산 가능
setState(5);

// 2. 함수형 업데이트 - 이전 상태 필요
setState(prev => prev + 1);
  • 직접 값 설정은 가능한 경우 즉시 처리하고
  • 함수형 업데이트는 이전 상태와의 관계를 고려하여 큐에서 순차적으로 처리합니다

참고 자료