React에서 성능 최적화를 하다 보면 React.memo를 자주 만나게 됩니다. 이름만 보면 컴포넌트 렌더링을 자동으로 줄여주는 도구처럼 느껴지지만, 실제로는 조건이 맞을 때만 효과가 있습니다.
특히 React.memo를 적용했는데도 자식 컴포넌트가 계속 렌더링된다면, 가장 먼저 봐야 할 것은 props의 참조 안정성입니다.
React.memo는 무엇을 비교할까?
React.memo는 컴포넌트의 이전 props와 다음 props를 비교합니다. 두 props가 같다고 판단되면 해당 컴포넌트의 렌더링을 건너뜁니다.
여기서 중요한 점은 기본 비교 방식이 얕은 비교라는 것입니다.
숫자, 문자열, boolean 같은 원시값은 비교가 쉽습니다. 값 자체가 같으면 같은 props로 볼 수 있습니다. 하지만 함수, 객체, 배열은 다릅니다. 이들은 값 자체가 아니라 참조값으로 비교됩니다.
즉, 내용이 같아 보여도 렌더링 때마다 새로 만들어지면 React는 다른 props로 판단합니다.
<ProductCard
product={{ id: 1, name: "기계식 키보드", price: 129000 }}
onAdd={(id) => console.log(`${id}번 상품을 담았습니다.`)}
/>
위 코드에서 product 객체와 onAdd 함수는 부모 컴포넌트가 렌더링될 때마다 새로 생성됩니다. 그래서 ProductCard에 memo를 적용해도 props가 바뀐 것으로 판단되어 다시 렌더링됩니다.
함수, 객체, 배열 props를 의심하자
React.memo가 기대처럼 동작하지 않을 때는 다음 props를 먼저 확인해야 합니다.
- 함수 props
- 객체 props
- 배열 props
이 props들이 렌더링마다 새로 만들어지고 있다면 memo는 큰 효과를 내기 어렵습니다.
이때 선택지는 크게 두 가지입니다.
첫 번째는 useMemo, useCallback으로 참조를 안정화하는 것입니다.
const product = useMemo(
() => ({
id: 1,
name: "기계식 키보드",
price: 129000,
}),
[]
);
const handleAdd = useCallback((id: number) => {
console.log(`${id}번 상품을 장바구니에 담았습니다.`);
}, []);
<ProductCard product={product} onAdd={handleAdd} />;
이렇게 하면 부모 컴포넌트가 다시 렌더링되어도 product와 handleAdd의 참조가 유지됩니다. ProductCard 입장에서는 props가 바뀌지 않았다고 판단할 수 있습니다.
두 번째는 props 구조를 단순하게 바꾸는 것입니다. 꼭 객체 하나로 전달할 필요가 없다면 id, name, price처럼 원시값 중심으로 나누어 전달하는 방식도 고려할 수 있습니다.
memo 비교도 비용이다
React.memo는 렌더링 전에 props를 비교합니다. 이 비교 과정도 비용입니다.
컴포넌트 렌더링이 매우 가볍거나 props가 거의 매번 바뀐다면 memo는 최적화가 아니라 불필요한 복잡도가 될 수 있습니다. 모든 컴포넌트에 습관적으로 memo를 붙이면 오히려 코드의 의도를 파악하기 어려워집니다.
memo는 “이 컴포넌트는 부모가 자주 렌더링되어도 같은 props라면 다시 렌더링하지 않아도 된다”는 의도를 드러낼 때 의미가 있습니다.
실무에서 memo를 고려할 만한 경우
다음 조건에 해당한다면 React.memo를 검토해볼 만합니다.
- 자식 컴포넌트 렌더링 비용이 실제로 크다.
- 부모는 자주 렌더링되지만 자식 props는 자주 바뀌지 않는다.
- 리스트 아이템처럼 같은 구조의 컴포넌트가 많이 반복된다.
- React DevTools Profiler로 불필요한 렌더링이 확인됐다.
반대로 단순한 버튼, 텍스트, 작은 presentational component라면 굳이 memo를 붙이지 않는 편이 낫습니다. “혹시 모르니까” 붙이는 memo는 좋은 최적화 전략이 아닙니다.
정리
React.memo는 렌더링을 무조건 줄여주는 마법 같은 도구가 아닙니다. props 비교 비용이 있고, 함수·객체·배열 props의 참조가 매번 바뀌면 효과를 보기 어렵습니다.
실무에서는 먼저 렌더링이 실제 병목인지 확인하고, props 설계와 참조 안정성을 점검한 뒤, 필요한 컴포넌트에만 memo를 적용하는 것이 좋습니다.
memo를 먼저 붙이기보다, 왜 렌더링되는지부터 확인하는 습관이 더 좋은 최적화의 출발점입니다.
'React,Next' 카테고리의 다른 글
| Next.js Server Component와 Client Component 기준 (0) | 2026.07.27 |
|---|---|
| React 렌더링 비용과 브라우저 렌더링 비용의 차이 (0) | 2026.07.20 |
| React Context와 useSyncExternalStore 차이 이해하기 (0) | 2026.07.19 |
| React Context와 memo, 왜 다시 렌더링될까? (1) | 2026.07.18 |
| React key는 왜 중요할까? index key가 위험한 이유 (1) | 2026.07.15 |
