useMemo 에서 memo 는 memoization 을 뜻하는데 이는 그대로 해석하면 메모리에 넣기 라는 의미이며 컴퓨터 프로그래밍이
동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여
실행 속도를 빠르게 하는 기술입니다.
memoization
기존에 수행한 연산의 결괏값을 어딘가에 저장해 두고 동일한 입력이 들어오면 재활용하는 프로그래밍 기법 입니다.
만약 어떤 함수가 있을 때 해당 함수가 들어있는 컴포넌트가 리렌더링 된다면 모든 내부 변수가 초기화 되기 때문에
함수도 다시 만들어지게 됩니다. 하지만 useMemo 를 사용한 함수는 컴포넌트가 리렌더링 된다면 memorize 된 함수를 재사용하기 때문에 함수를 새로 만들지 않습니다.
설명
useMemo 는 첫번째 인자로 콜백 함수를, 두번째 인자로 의존성 배열을 넣습니다.
import { useMemo } from "react";
const add = useMemo(callback, [])
위 코드에서 두번째 인자인 배열의 요소 값이 업데이트 될 때만 콜백 함수를 다시 호출시켜 memoization 된 값을 업데이트 해주고 다시 memoization 을 해줍니다. 만약 빈 배열을 넘겨주면 맨 처음 컴포넌트가 렌더링 될 때만 memoization 하고 항상 그 값을 재사용 합니다.
주의점
값을 재활용 하기 위해서 메모리에 따로 저장해 두기 때문에 불필요한 값을 메모리에 저장한다면 성능이 안좋아 질 수 있기 때문에 꼭 필요한 경우만 사용하는 것을 추천합니다.
사용법
예시 - 1
const user = { name: 'chan', age: 24 }
useEffect = (() => {
console.log("useEffect" 호출)
}, [user])
만약 이러한 코드가 있다면 컴포넌트가 리렌더링 됐을때 console.log 가 호출이 될까요??
네 호출이 됩니다. 이는 리액트의 불변성 때문인데요. 리액트에서는 컴포넌트가 리렌더링 되면 해당 컴포넌트 내부에 있는 객체의 참조값이 변경이 됩니다. 이유는 간단합니다. 내부의 값이 변경되더라도 참조값이 같으면 리액트는 변경사항을 인식하지 못합니다. 그래서 불변성을 유지하여 객체가 변경될 때마다 새로운 객체를 생성하면, 리액트는 참조값이 변경되었다고 감지하여 올바른 업데이트를 수행할 수 있습니다.
따라서 만약 user 을 useEffect 의 배열에서 사용해야 한다면 밑에 코드처럼 바꾸시면 됩니다.
const user = useMemo({name: 'chan', age: 26}, [])
useEffect = (() => {
console.log('useEffect 호출')
},[user])
예시 - 2
함수를 사용하는 경우입니다. 만약 엄청나게 복잡하고 계산이 오래 걸리는 함수가 있다고 가정해 봅시다.
그럴때 함수를 재사용하기 위해 useMemo 를 사용해야 합니다. 하지만 궁금증이 들 수 있습니다. 함수인데 왜 useCallback 함수를 쓰지 않고 useMemo 를 써야 하는걸까? 그 이유는 useCallback 은 함수 자체를 재사용 하는 반면에 useMemo 는 계산한 값을 재사용 하기 때문입니다. 따라서 함수 안에서 return 문이 있다면 useMemo 를 써야 합니다.
const add = useMemo(() => {
... 엄청 복잡한 함수.....
return 값..
}, [])
function Component() {
const value = calculate();
return <div>{value}</div>
}
결론
만약 useEffect 의 두번째 인자로 객체나 함수가 들어갈 경우 또는 정말 복잡한 계산 값이 있을 경우 쓰는 것이 좋습니다.
그 외에는 메모리만 잡아먹으니 쓰지 않도록 합시다.
'React' 카테고리의 다른 글
Axios (0) | 2024.07.28 |
---|---|
React Redux (0) | 2024.07.10 |
useCallback (0) | 2024.05.03 |
useEffect (0) | 2024.05.01 |
useState (0) | 2024.01.07 |