React, Vue

React 컴포넌트 최적화 ✅ React.memo, useMemo, useCallback

jonbeo 2025. 10. 22. 09:35
반응형

 

 

리액트는 상태가 변경되면 관련된 컴포넌트를 다시 렌더링하는 방식으로 동작합니다.
하지만 이 과정에서 필요 없는 컴포넌트까지 렌더링되면 성능 저하로 이어지죠.
이를 방지하기 위해 메모이제이션(Memoization) 기법을 활용합니다.


🧠 1. React.memo

컴포넌트 자체를 메모이제이션하여 불필요한 리렌더링 방지

 
import React from "react";

const Child = React.memo(({ value }) => {
  console.log("렌더링됨:", value);
  return <div>{value}</div>;
});

export default Child;
  • props가 바뀌지 않으면 다시 렌더링하지 않음
  • PureComponent와 비슷한 개념

📌 주의: props가 객체/배열일 경우 참조가 바뀌면 여전히 리렌더링 발생 → useMemo, useCallback과 함께 사용해야 함


🧮 2. useMemo

값(연산 결과)을 메모이제이션 → 비싼 연산 최적화

 
import { useMemo } from "react";

const ExpensiveCalc = ({ num }) => {
  const result = useMemo(() => {
    console.log("무거운 연산 실행");
    return num * 1000;
  }, [num]);

  return <div>{result}</div>;
};
  • 의존성 배열([num])이 변하지 않으면 캐싱된 값 재사용
  • 성능이 무거운 연산에만 사용해야 함 (남용 금지)

🪝 3. useCallback

함수 정의를 메모이제이션 → 자식 컴포넌트에 불필요하게 새로운 함수 전달되는 것 방지

 
import { useState, useCallback } from "react";
import Child from "./Child";

const Parent = () => {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log("버튼 클릭");
  }, []); // 의존성 배열이 없으므로 항상 같은 함수 유지

  return (
    <>
      <button onClick={() => setCount(count + 1)}>+</button>
      <Child onClick={handleClick} />
    </>
  );
};

 

📌 useCallback이 없으면 매 렌더링마다 새로운 함수가 생성 → 자식이 불필요하게 리렌더링됨


⚡ 4. 세 가지 최적화 기법 요약

Hook / 기능 최적화 대상 사용 예시
React.memo 컴포넌트 props 변하지 않으면 렌더링 방지
useMemo 값 (연산 결과) 무거운 계산, 필터링, 정렬
useCallback 함수 자식에게 전달하는 핸들러

 


🧠 5. 실무 적용 팁

  • ✅ 무조건 쓰지 말고, 성능에 문제가 되는 곳에서만 사용
  • ✅ props로 객체/배열/함수를 넘기는 경우 → useMemo, useCallback 병행
  • ✅ 리스트/테이블 컴포넌트 성능 최적화에 효과적
  • ✅ 너무 남용하면 코드 가독성 떨어짐 → 병목 지점에만 사용

📝 마무리 정리

  • React.memo → 컴포넌트 자체 최적화
  • useMemo → 값 연산 최적화
  • useCallback → 함수 참조 최적화
  • React 프로젝트에서 성능 최적화는 “필요할 때만, 정확히” 하는 것이 핵심입니다 ⚡
반응형