상태 내리기(State Colocation)는 state를 실제로 쓰는 컴포넌트 가까이로 옮겨, state가 바뀔 때 다시 렌더되는 범위를 좁히는 기법이다. 메모이제이션(Memoization)보다 먼저 시도할 구조적 최적화다.
- 리렌더는 state가 바뀐 컴포넌트와 그 아래로 흐른다. 페이지 최상단에 입력창 state를 두면 타이핑할 때마다 페이지 전체가 렌더된다. 입력창 컴포넌트 안으로 내리면 그 컴포넌트만 렌더된다
- children으로 받은 부분은 리렌더되지 않는다. 바뀌는 state를 가진 래퍼가 무거운 부분을
children으로 받으면, children 엘리먼트는 부모 쪽에서 이미 만들어진 것이라 래퍼가 다시 렌더돼도 다시 만들어지지 않는다
function ScrollTracker({ children }) { // 스크롤 위치 state는 여기만
const [y, setY] = useState(0)
return <div onScroll={e => setY(e.currentTarget.scrollTop)}>{children}</div>
}
<ScrollTracker><HeavyList /></ScrollTracker> // HeavyList는 다시 렌더되지 않음- 렌더할 내용을 함수로 넘기는 Render Props 패턴도 같은 효과를 낸다
- 커스텀 훅으로 분리한다고 리렌더가 줄지는 않는다. 훅은 로직을 추상화할 뿐 state는 여전히 그 컴포넌트에 있다
- 이 과정은 컴포넌트가 한 가지 책임만 갖게 만드는 일이기도 하다(SOLID 원칙, 응집도)
- 측정 → 구조 개선 → 그래도 필요하면 memo·useMemo·useCallback 순서로 간다. 재조정 규칙은 재조정(Reconciliation)