노트

상태 내리기와 컴포지션으로 리렌더 줄이기

State Colocation

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

쉽게 말하면

상태 내리기는 state를 실제로 쓰는 컴포넌트 가까이 옮겨서, 값이 바뀔 때 다시 그려지는 범위를 좁히는 거예요. 방 하나 불을 켜려고 집 전체 차단기를 내렸다 올리지 않고 그 방 스위치만 누르는 셈이죠.

비유가 깨지는 곳 커스텀 훅으로 빼는 건 스위치를 옮긴 게 아니에요. state는 여전히 그 컴포넌트에 있어 리렌더가 줄지 않아요. 반대로 children으로 받은 부분은 래퍼가 다시 렌더돼도 다시 만들어지지 않아요.

상태 내리기(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)

출처: Beyond React.memo: Smarter Performance Optimization

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • React Compiler

    React Compiler는 빌드 타임에 컴포넌트와 훅을 분석해 메모이제이션(Memoization) 코드를 자동으로 넣어 주는 컴파일러다. 개발자가 손으로 붙이던 useMemo·useCallback·memo를 대신한다. 2025년 10월 1.0이 나왔다.

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

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

  • 구성요소 줄이기

    셀 수 있는 모든 구성요소(파일, 폴더 깊이, 클래스, 함수, 분기, 변수, 테이블, 필드, 테스트 케이스…)는 비용이라는 관점. 심플 디자인의 네 번째 규칙을 실무 기준으로 풀어낸 것이다.

  • Effect가 필요 없는 경우

    Effect는 외부 시스템과 동기화할 때 쓰는 탈출구(Escape Hatch)다. 렌더 중에 계산할 수 있는 값이나 사용자 이벤트 처리에 Effect를 쓰면 렌더가 한 번 더 일어나고 흐름이 꼬인다. React 공식 문서가 이런 경우를 따로 정리해 두었다.

  • 변수·컬렉션 캡슐화

    넓은 범위에서 쓰이는 데이터에 직접 접근하지 못하게 하고, 읽고 쓰는 함수를 통해서만 다루게 하는 리팩터링. 데이터를 옮기거나 바꿀 때 고쳐야 할 곳이 접근 함수 한 곳으로 좁아진다.

보기 옵션