개발 TIL
24.07.22 day30 useMemo, useCallback
문미새
2024. 7. 22. 22:45
728x90
useMemo
리액트의 useMemo는 성능 최적화를 위해 사용되는 훅이며, 특정 값이나 연산이 필요할 때 그 값을 메모이제이션(Memoization)하여 재계산을 피하고, 의존성 배열에 지정된 값들이 변경되었을 때만 재계산을 하도록 하는 기능이다.
여기서 메모이제이션은 성능 최적화를 위해 컴포넌트의 특정 계산 결과를 저장하고, 필요할 때만 재계산하여 불필요한 계산을 피하는 기술이다. 메모이제이션은 주로 컴포넌트의 렌더링 성능을 최적화하기 위해 사용된다.
메모이제이션의 필요성
리액트 컴포넌트는 상태나 프롭스가 변경될 때마다 리렌더링되는데, 복잡한 계산이나 큰 데이터를 다루는 경우, 매번 리렌더링하면 성능 저하가 발생할 수 있기 때문에 메모이제이션을 사용하여 특정 연산의 결과를 저장해두고, 필요한 경우에만 계산을 수행함으로써 이러한 문제를 해결할 수 있다.
useMemo 기본 문법
const memoization = useMemo(() => {
return hamsu(a, b);
}, [a, b]);
동작 방식
- useMemo는 첫 번째 인수로 제공된 함수(예: hamsu)를 실행하여 그 결과를 메모이제이션한다.
- 두 번째 인수로 의존성 배열을 받는데, 이 배열에 포함된 값들이 변경되지 않는 한, 메모이제이션된 값을 반환한다.
- 의존성 배열의 값 중 하나라도 변경되면, 첫 번째 인수로 제공된 함수를 다시 실행하여 새로운 값을 계산하고, 이를 메모이제이션한다.
사용 예시
useMemo는 일반적으로 두 가지 상황에 사용한다.
- 계산이 복잡하거나 시간이 많이 걸리는 경우, 필요할 때만 계산을 수행하도록 한다.
- 부모 컴포넌트가 리렌더링될 때 자식 컴포넌트가 불필요하게 리렌더링되는 것을 방지한다.
import React, { useMemo } from 'react';
function hamsu({ a, b }) {
// 비싼 계산을 useMemo로 최적화
const memoization = useMemo(() => {
return hamsuValue(a, b);
}, [a, b]);
return (
<div>{memoization}</div>
);
}
function hamsuValue(a, b) {
console.log('useMemo test');
return a + b;
}
주의사항
- useMemo는 최적화 도구일 뿐이며, 모든 경우에 불필요하게 사용하면 오히려 성능이 저하될 수 있다.
- 의존성 배열의 값들이 변경되었을 때만 함수가 다시 실행되므로, 의존성 배열을 정확하게 지정하는 것이 중요하다.
useCallback
리액트의 useCallback은 메모이제이션된 콜백 함수를 생성하는 데 사용되며, 컴포넌트가 리렌더링될 때마다 새로 생성되는 콜백 함수의 참조를 고정해 불필요한 재생성을 방지하는 데 유용하다.
useCallback 기본 문법
const memoizedCallback = useCallback(() => {
// 콜백 함수 로직
}, [a, b]);
동작 방식
- useCallback은 첫 번째 인수로 콜백 함수를 받는다.
- 두 번째 인수로 의존성 배열을 받는데, 이 배열에 포함된 값들이 변경되지 않는 한, 동일한 콜백 함수 참조를 반환한다.
- 의존성 배열의 값 중 하나라도 변경되면, 새로운 콜백 함수가 생성된다.
사용 예시
useCallback은 주로 두 가지 경우에 사용한다.
- 자식 컴포넌트에 함수를 프롭스로 전달할 때 부모 컴포넌트가 리렌더링될 때마다 자식 컴포넌트가 불필요하게 리렌더링되는 것을 방지한다.
- 콜백 함수가 복잡한 연산을 포함하는 경우, 비용이 큰 연산이 포함된 콜백 함수의 재생성을 피하기 위해 이를 재사용하여 성능을 최적화한다.
import React, { useState, useCallback } from 'react';
function ParentComponent() {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prevCount => prevCount + 1);
}, []);
return (
<div>
<ChildComponent onClick={handleClick} />
<p>Count: {count}</p>
</div>
);
}
function ChildComponent({ onClick }) {
return (
<button onClick={onClick}>Increment</button>
);
}
- handleClick 함수는 useCallback을 사용하여 메모이제이션된다.
- count가 변경되어 부모 컴포넌트가 리렌더링되어도 useCallback에 의해 handleClick 함수는 새로 생성되지 않으므로, ChildComponent는 불필요하게 리렌더링되지 않는다.
- useCallback의 의존성 배열은 콜백 함수가 의존하는 모든 값을 포함해야 하는데, 배열에 포함된 값 중 하나라도 변경되면, useCallback은 새로운 콜백 함수를 생성한다.
주의사항
- useCallback의 의존성 배열을 정확하게 관리해야 하며, 잘못된 의존성 배열은 의도치 않은 동작을 초래할 수 있다.
- useMemo와 마찬가지로 모든 경우에 useCallback을 사용하면 오히려 성능이 저하될 수 있기 때문에 성능 문제를 실제로 겪고 있는 부분에만 신중하게 적용하는 것이 중요하다.
useCallback vs useMemo
- useCallback은 콜백 함수를 메모이제이션하는 데 사용되며, 함수를 프롭스로 전달하거나, 함수 참조의 변경을 피하기 위해 사용된다.
- useMemo는 메모이제이션된 값을 계산하는데 사용되며, 비싼 계산 결과를 저장하고, 필요할 때만 재계산하여 성능을 최적화할 때 사용된다.
728x90