[React] React hook의 useCallback 이란?
useCallback
메모이제이션 기법으로 컴포넌트 성능을 최적화 시켜주는 도구
💡 메모이제이션 이란?
이전에 계산한 값을 메모리에 저장해두고, 동일하게 다시 사용할 수 있는 곳에서 재사용하여 반복적으로 발생하는 계산의 리소스를 줄이는 기법
- useMemo() : 자주 쓰이는 값을 메모이제이션 즉 캐싱해주는 것, 그리고 그 값이 필요할 때 다시 계산하는 것이 아닌 useMemo를 통해 캐싱을 한 값을 메모리에서 꺼내와서 재사용하고 인자로 콜백함수를 넣어주면 함수가 리턴하는 값을 메모이제이션 하는 것
- useCallback() : 인자로 전달한 콜백 함수 그 자체를 메모이제이션하는 것, 첫번째 인자로 넘어온 함수를 두번째 인자로 넘어온 배열 내의 값이 변경될 때까지 정장해놓고 재사용할 수 있게 함
📝 useCallback 구조
const memoizedCallback = useCallback(함수, 배열);
📝 useCallback 사용예시
1. 콜백함수가 자식 컴포넌트에 props로 전달되는 경우
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<ChildComponent onClick={handleClick} />
</div>
);
}
function ChildComponent({ onClick }) {
return (
<button onClick={onClick}>Click me</button>
);
}
handleClick 함수가 ParentComponent 컴포넌트에서 생성되어 ChildComponent 컴포넌트에 props로 전달
만약 useCallback을 사용하지 않으면 ParentComponent가 리렌더링 될 때마다 handleClick 함수가 새로 생성됨
이 경우 ChildComponent는 onClick props가 변경되었으므로 불필요한 리렌더링을 발생
➡️ 이를 방지하기 위해 useCallback을 사용하여 handleClick함수를 메모이제이션함
2. 콜백함수가 의존성 배열에 있는 경우
function ParentComponent() {
const [count, setCount] = useState(0);
const [text, setText] = useState('');
const handleChangeText = useCallback((e) => {
setText(e.target.value);
}, []); // handleChangeText 함수는 의존성이 없음
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, [count]); // handleClick 함수는 count 변수에 의존함
return (
<div>
<input type="text" value={text} onChange={handleChangeText} />
<button onClick={handleClick}>Click me ({count})</button>
</div>
);
}
handleChangeText 함수는 text 상태만을 참조하므로 의존성 배열이 비어있음
handleClick 함수는 count 상태를 참조하므로 의존성 배열에 count를 추가해줌
count가 변경될 때마다 handleClick함수가 새로 생성됨
➡️ 이를 방지하기 위해 useCallback을 사용하여 handleClick함수를 메모이제이션함
3. useEffect와 같이 사용해 컴포넌트 최적화하는 경우
import React, { useCallback, useEffect, useState } from "react";
function ExampleComponent(props) {
const [data, setData] = useState([]);
const fetchData = useCallback(async () => {
const response = await fetch("https://example.com/data");
const data = await response.json();
setData(data);
}, []);
useEffect(() => {
fetchData();
}, [fetchData]);
return (
<div>
{data.map((item) => (
<div key={item.id}>{item.name}</div>
))}
</div>
);
}
export default ExampleComponent;
useCallback과 useEffect를 사용하여 데이터를 불러오는 fetchData함수를 최적화해주는 코드
useEffect의 의존성 배열에 fetchData함수를 추가하여, fetchData 함수가 변경될 때에만 useEffect가 실행되도록 함
➡️ 컴포넌트가 렌더링될 때마다 fetchData함수가 새로 생성되는 것을 방지하고, fetchData함수가 변경될 때에만 데이터를 다시 불러오도록 최적화함