useCallback 은 함수를 cache 로 저장 해서 re-render 할 때 사용할 수 있도록 하는 React Hook 이다.
아 슈밤 글 다썼는데 코드로 테스트하다가 다 날라갔다... ㅠㅠ
loop 3중첩으로 1000*1000*1000 으로 돌리니까 브라우저 바로 뻑나네.............
ProductPage가 리렌더링 되면 handleSubmit 함수는 새롭게 생성될까?
아니면 동일한 로직의 함수이니 알아서 이전 렌더링 때 만든 handleSubmit 함수를 그대로 사용할까?
정답은 함수를 새롭게 생성한다. 자바스크립트에서 function () {} 혹은 () => {} 인 경우에는 함수를 새로 생성하기 때문이다.
이런식으로 함수를 useCallback 으로 감싸고 dependency array 에 react value 들을 넣어주면 된다.
그러면 dependecy array 에 있는 value 들이 바뀔 때만 handleSubmit 을 재생성하고
바뀌지 않을 때는 이전 렌더링 때 생성한 handleSubmit 을 그대로 사용하여 최적화가 이루어진다.
위의 예시에서 todos 가 dependency array 에 있다.
setTodos 에서 todos 를 사용하기 때문이다.
그래서 handleAddTodo 가 수행되면 todos 가 변경되고, handleAddTodo 도 재생성된다.
위의 코드를 updater function 을 사용해 개선할 수 있다.
setTodos(todos => [...todos, newTodo]); 의 todos는 state 의 todos 가 아니다.
setTodos(prevState => [...prevState, newTodo]); 로 바꿀 수 있다.
즉 마치 함수형 프로그래밍을 하듯 함수로 바꿔주면
handleAddTodo 내에서 todos 를 사용하지 않게 되고
dependency 에서 todos 를 제거할 수 있다.
따라서 handleAddTodo 가 실행되어 todos 가 변경되어도 handleAddTodo 는 재생성하지 않게 되고
기존의 기능은 그대로 수행하기 때문에 더 좋은 최적화를 할 수 있다.
(즉, dependecy array 에는 최대한 적은 value 들이 있는게 좋다.)
공식 문서에는 없는 또다른 방법
import { useCallback } from 'react';
import ShippingForm from './ShippingForm.js';
function handleSubmit(orderDetails, productId, referrer) {
post('/product/' + productId + '/buy', {
referrer,
orderDetails,
});
}
export default function ProductPage({ productId, referrer, theme }) {
return (
<div className={theme}>
<ShippingForm onSubmit={handleSubmit} productId={productId} referrer={referrer} />
</div>
);
}
function post(url, data) {
// Imagine this sends a request...
console.log('POST /' + url);
console.log(data);
}
위의 코드처럼 handleSubmit 을 ProductPage 외부로 빼는 방법 가능하다.
이 경우 ProductPage가 리렌더링 되더라도 handleSubmit 은 재생성하지 않는다.
다만 ShippingForm 에 productId 와 referrer 를 전달하고 있는데
props drilling 이 발생하는 단점이 있겠다.
공식 문서에는 없지만 하나를 추리할 수 있다.
useCallback을 이용해 함수를 재생성하는 것을 막아 최적화를 할 수 있다 -> 즉, 함수를 생성하는 것은 오버헤드이다.
위의 예시는 간단한 함수라 useCallback 을 쓰냐 안쓰냐에 따라 큰 차이가 없겠지만
극단적인 예로 10000줄 짜리 함수라면 성능을 훨씬 좋게 만들 수 있을 것이다.
(물론 그런 함수는 만들지 않아야 겠지만)
useCallback을 많이 사용하면 브라우저 캐시나 메모리를 많이 사용하게 되진 않을까?
useCallback이 함수를 cache 에 저장하니까 useCallback을 마구 남발하면 그만큼 브라우저의 메모리를 많이 사용하게 되니까 성능에 악영향을 미치진 않을까
그런데 이와 관련한 내용은 공식 문서에 없었다.
크게 상관은 없는 것 같다.
회사 코드에 useCallback 적용하기
회사에 "릴레이 특가" 페이지에 1초마다 남은 시간이 1초씩 줄어드는 코드가 있었다.
함수가 복잡하진 않았지만 1초마다 실행되기 때문에
자주 실행된다고 생각하여 useCallback 을 사용해 최적화를 해줬다.
React.dev 문서에 따르면, 느려지는 부분이 느껴진다면 React Developer Tools의 profiler 로 확인하여 useCallback 이나 memo 를 활용하라고 적혀있다. 추후에도 이 툴을 이용해 최적화 작업 진행 해보려고 한다.
'dev' 카테고리의 다른 글
2023년 하반기 회고 - 이커머스 프론트엔드 개발, 애자일, 스토리북, 테스트 코드, 사이드 프로젝트 (1) | 2023.12.28 |
---|---|
useEffect로 Race Condtions 해결하는 방법 (2) | 2023.11.22 |
useDeferredValue 는 언제, 어떻게 쓰는걸까? (0) | 2023.11.05 |
강원랜드 카지노 필승법 카드 카운팅 웹앱 개발 후기 (1) | 2023.10.05 |
jest 라이브러리 import 문제 해결 방법 (SyntaxError: Unexpected token 'export') (0) | 2023.08.13 |
댓글