우리는 어떤 일을 할 때 과거의 기억을 활용한다. 카메라를 활용할 때에는 카메라에 대한 기억이 단서가 된다.처음 보는 카메라라도, 우리는 카메라에 대한 기억을 통해 하나하나 뜯어보는 대신 뻔한 것들을 건너뛰고 새로운 정보를 이해하고 처리한다. 시스템 역시도 그렇게 반복될 내용들을 기억할 수 있다면 더 빠른 처리가 가능해질 것이다.
useMemo는 그러한 캐싱(caching)을 해주는 훅이다. 캐싱이란 과거에 처리했던 데이터를 임시적으로 저장하여 새로운 처리에 활용하도록 하는 것을 의미하는데, useMemo는 이러한 기억의 역할을 한다. 기본적으로 리액트는 어떤 컴포넌트를 호출할 때마다 그 내부에 선언된 기능을 다시 실행하는데, 컴포넌트가 복잡하다면 이는 많은 낭비를 초래한다. 데이터에 변화가 있다면 당연히 새롭게 렌더링을 해야하겠지만, 데이터가 변하지 않았는데도 많은 계산을 매번 반복한다면 위의 카메라의 예시에서 새로운 카메라를 만날 때마다 뻔한 특징들을 하나하나 살펴보고 있는 꼴이 된다. 이를 피하는 캐싱이 메모이제이션(memoization)이다.
메모라이제이션(memorization)과 비슷해 보이지만 다른 개념이다. 처음에 리액트 문서에 난 오타인가 싶어 찾아보았는데, 메모이제이션은 이렇게 동적인 계산을 반복하지 않도록 하는 캐싱 전략을 의미하는 말로, 단순히 기억을 의미하는 memorization과 용어와 쓰임이 분명히 구별된다.
useMemo는 아래와 같이 사용된다.
const cachedValue = useMemo(calculateValue, dependencies)
상수 cachedValue는 useMemo로 선언되는 값인데, useMemo는 두 가지 인자를 통해 만들어진다. 이 중 첫번째인 calculateValue는 함수인데, cachedValue를 계산하는 함수를 의미한다. 두 번째 인자는 dependencies라는 예시명을 보듯이 의존성 배열인데, useEffect에서 그러하였듯이 이 의존성 배열이 변하면 useMemo는 다시 수행되고, 변하지 않으면 기존에 캐시되어 있던 값을 그대로 활용한다.
import { useMemo } from 'react';
function TodoList({ todos, tab }) {
const visibleTodos = useMemo(
() => filterTodos(todos, tab),
[todos, tab]
);
// ...
}
위의 리액트 문서에 든 예시를 통해 다시 살펴보면, useMemo를 통해 visibleTodos라는 상수가 선언되는데, 이 useMemo는 filterTodos라는 기능을 통해 값을 만들어내며 [todos, tab]을 의존성 배열로 갖는 상태이다. 즉, todos나 tab이 변하지 않으면 기존에 기억된 visibleTodos를 활용해 TodoList라는 컴포넌트를 호출하는데, 만약 이 과정이 복잡한 기능을 통해 수행된다면 많은 낭비를 줄일 수 있다.
위의 사례는 단편적이지만, 실제로는 훨씬 더 효율적으로 프로세스를 줄여줄 수 있는데, 왜냐하면 일반적으로 리액트에서의 컴포넌트들은 중첩되어 부모-자식의 관계를 가지며, 그런 경우 부모의 호출은 그 자손 모두의 재호출을 의미하기 때문이다. 이러한 상태에서 부모요소가 useMemo를 통해 효율적으로 재호출을 피한다면 그에 따린 자손 모두가 무의미한 계산을 피하게 되어 상당히 큰 부분에서 효율성을 얻을 수 있다.
주의할 점은, 두번째 인자인 의존성 배열 부분을 통해 이 기능이 수행되어야 하는지가 결정된다. 따라서 이 부분이 비어있으면 useEffect에서와 마찬가지로 매번 기능이 수행되어 useMemo로 지정한 보람이 없어지게 된다. useMemo의 주요한 기능이 의존성 배열을 참고하여 불필요한 재생성을 막는 것인 만큼, 의존성을 정확하게 표기하여 이 주요 기능이 잘 동작할 수 있도록 해야 한다.
'React.Native' 카테고리의 다른 글
[QML] 레이아웃 잡기 : Grid, Row, Column (0) | 2024.11.24 |
---|---|
[React] 시스템의 공영 방송: Context API (0) | 2024.11.17 |
[React] Props는 통신용이 아니다 : Props 진짜 이해하기 (3) | 2024.11.15 |
[React] 값 참조하기: useRef (0) | 2024.11.12 |
[React] useEffect와 정리함수(clean up) (10) | 2024.11.10 |