[React]리액트 성능 최적화 (2): useCallback과 함수 주소

정호·2024년 3월 25일

React

목록 보기
17/30

리액트 성능 최적화 (2): useCallback과 함수 주소 박제

useCallback은 리액트에서 함수 자체를 메모리에 저장(캐싱)해두고 재사용하기 위해 사용하는 도구임

리액트 컴포넌트는 상태가 바뀌면 함수 전체가 다시 실행된다. 이때 내부에 선언된 함수들도 매번 새로 만들어지는데, 이를 방지하는 것이 useCallback의 핵심 역할이다.


useCallback을 쓰는 진짜 이유

자바스크립트에서 내용은 같아도 '새로 만든 함수'는 이전 함수와 다른 주소값을 가진다. 이 미세한 차이가 리액트 성능에 큰 영향을 미친다.

함수 재생성의 문제점:

  • 참조값 변화: 리렌더링 시 함수가 새로 만들어지면 주소값이 바뀜
  • 자식의 오해: memo를 사용 중인 자식 컴포넌트에 이 함수를 전달하면, 자식은 "어? Props(함수 주소)가 바뀌었네?"라고 착각하여 불필요하게 다시 그려짐

useCallback은 "이 함수는 데이터가 바뀌지 않는 한, 새로 만들지 말고 예전에 만든 거 그대로 써!"라고 리액트에게 지시하는 것이다.


실전 예시와 의존성 배열

const handleRemovePlace = useCallback(
  async function handleRemovePlace() {
    // ... 이 안에서 userPlaces 상태를 참조함
    console.log(userPlaces);
  },
  [userPlaces, setUserPlaces] // 👈 의존성 배열
);

useCallback 작동 프로세스

  1. 메모리 저장: 함수가 처음 생성될 때 그 주소값을 메모리에 박제함
  2. 의존성 체크: 배열 안에 넣은 userPlaces 값이 변경되었는지 확인함
  3. 업데이트: 값이 바뀌었을 때만 함수를 새로 만들어 최신 데이터를 반영하고, 그렇지 않으면 기존 주소를 재사용함

의존성 배열([ ])의 중요성 (클로저 문제)

함수는 만들어질 당시의 변수 값들을 기억한다. 만약 의존성 배열을 잘못 관리하면 '과거의 데이터'에 갇히는 버그가 발생한다.

❖ 의존성 배열 관리 규칙:

  • 비워둘 때([]): 컴포넌트가 처음 생길 때의 옛날 데이터만 계속 기억함 (클로저 문제 발생)

  • 상태 포함([userPlaces]): 해당 상태가 바뀔 때마다 함수도 최신 데이터를 알 수 있게 업데이트됨

  • 함수 내부에서 참조하는 모든 상태와 Props는 반드시 의존성 배열에 포함해야 안전함

profile
열심히 기록할 예정🙃

0개의 댓글