본문 바로가기
C.W.K.
Stream
Lesson 05 of 06 · published

수동 메모이제이션이 필요한 자리

~10 min · usememo, react.memo, edge-cases

Level 0React 입문자
0 XP0/54 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
Compiler가 많은 메모이제이션을 맡아도 수동 최적화가 필요한 자리는 남아. 안정된 참조가 외부 계약인 곳과 측정된 병목을 구분해.

외부 API가 참조 동일성을 요구할 때

Three.js, Web Worker bridge, Web Component처럼 React 밖의 API가 콜백이나 객체의 참조로 변경을 판단할 수 있어. React Compiler의 최적화만 믿기보다 useCallback이나 useMemo로 그 외부 계약을 명시하는 편이 안전해.

비싼 계산을 측정으로 확인했을 때

DOM 측정값, 현재 시간, 큰 lookup table처럼 Compiler가 추적하기 어려운 입력으로 실제 비용이 큰 계산을 한다면 수동 useMemo가 도움이 될 수 있어. 먼저 Profiler로 비용을 확인하고 입력이 바뀔 때만 다시 계산하게 해.

긴 목록의 개별 항목이 비쌀 때

한 행의 변경 때문에 바뀌지 않은 수백 개 행까지 다시 렌더링된다면 Row를 React.memo로 감싸는 경계가 분명한 효과를 낼 수 있어. Compiler 사용 여부와 관계없이 의도가 코드에 드러난다는 장점도 있어.

Compiler를 쓰지 않는 프로젝트일 때

기존 코드베이스가 Compiler를 켜지 않았다면 수동 메모이제이션이 여전히 필요한 도구야. 프로젝트의 빌드 설정과 기존 스타일을 확인하고 같은 기준을 따라.

수동 memo는 기본 습관이 아니라 이유가 있는 정밀 도구야. 외부 API 계약이나 측정된 병목, 비싼 목록, Compiler가 없는 환경처럼 구체적인 근거가 있을 때 사용해.

Dependency가 늘 바뀌면 memo도 매번 다시 계산해

렌더링마다 새 객체나 함수를 dependency로 만들면 useMemo와 useCallback은 캐시를 거의 재사용하지 못해. 먼저 입력 참조가 왜 바뀌는지 확인하고, 계산 비용보다 dependency 비교와 코드 복잡성이 더 큰지 측정해.

React.memo도 prop을 얕게 비교하므로 자식에게 매번 새 객체를 넘기면 건너뛰지 못해. 목록 행을 감쌀 때는 key와 prop 모양, callback 참조를 함께 살펴봐.

외부 라이브러리가 callback 참조 동일성을 구독 해제 조건으로 사용할 때가 있어. Context value의 안정성이 넓은 트리의 렌더링을 좌우하는 경우도 있어서, 이때는 수동 memoization이 성능을 넘어 계약의 일부가 될 수 있어.

Code

React.memo 있는 리스트 아이템: 여전히 유용·tsx
import { memo } from "react";

type Item = { id: string; label: string };

// memo 없으면: 모든 부모가 다시 렌더링되면 바뀌지 않은 Row까지 모두 다시 렌더링돼.
// memo 있으면: Row는 자기 prop이 바뀔 때만 다시 렌더링돼.
const Row = memo(function Row({ item, onClick }: {
  item: Item;
  onClick: (id: string) => void;
}) {
  return (
    <li onClick={() => onClick(item.id)} className="px-3 py-2 hover:bg-bg-elevated">
      {item.label}
    </li>
  );
});

function List({ items, onItemClick }: { items: Item[]; onItemClick: (id: string) => void }) {
  return (
    <ul>
      {items.map((item) => <Row key={item.id} item={item} onClick={onItemClick} />)}
    </ul>
  );
}

// (Compiler가 활성화되면 onItemClick의 참조도 자동으로 안정돼 — 다만 큰 리스트의
// row 레벨에선 React.memo가 여전히 밥값 함.)

External links

Exercise

각 행에 click handler가 있는 500개 항목 목록을 만들고 한 행을 바꿀 때 몇 개의 Row가 다시 렌더링되는지 Profiler로 기록해. Row를 React.memo로 감싼 뒤 같은 상호작용을 반복하고 commit 시간과 렌더링 행 수를 비교해. React Compiler도 켠 상태에서 memo가 여전히 이득을 주는지 확인하고, 20개짜리 작은 목록에서는 복잡성보다 이득이 큰지도 별도로 판단해.
Hint
새 객체나 callback을 매번 넘기면 React.memo가 건너뛰지 못할 수 있어. 변경 전, memo 적용 뒤, Compiler와 함께 쓴 뒤의 세 측정값을 같은 production preview에서 비교해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.