7-1강. Hooks - useMemo ( ), useCallback( )

정원·2023년 1월 31일
0

React

목록 보기
20/42

2023.01.31 useMemo( ) ,useCallback( )

메모이제이션이란? (Memoization)

useMemo( )와 useCallBack( ) 훅에서는 메모이제이션이라느 개념이 나온다.

  • 컴퓨터 분야에서 메모이제이션은 최적화를 위해서 사용하는 개념이다.
  • 비용이 높은(연산량이 많이 드는) 함수의 후출 결과를 저장해 두었다가,
    같은 입력값으로 함수를 호출하면 새로 함수를 호출하지 않고
    이전에 저장해놨던 호출 결과를 바로 반환하는 것.
  • 결과적으로 함수 호출 결과를 받기까지 걸리는 시간도 짧아질뿐더러
    불필요한 중복 연산도 하지 않기떄문에 컴퓨터의 자원을 적게쓴다.

Momoized value

메모이제이션이 된 결괏값을 메모이즈드 밸류라고 한다.


useMemo( ) 란?

useMemo( ) 훅은 Memoized value(값)를 리턴하는 혹이다.

뒤에 나을 메모이제이션의 개념처럼
의존성 배열에 들어있는 변수가 변했을 경우에만 새로 create 함수를 호출하여 결괏값을 반환하며,
그렇지 않은 경우에는 기존 함수의 결괏값을 그대로 반환한다.

useMemo( ) 훅을 사용하면 컴포넌트가 다시 렌더링될 때마다 연산량이 높은 작업을 반복하는 것을 피할 수 있다.
결과적으로는 빠른 렌더링 속도를 얻을 수 있다.

useMemo( ) 선언

  • 파라미터로 Memoized value를 생성하는 create 함수와 의존성 배열을 받는다.
useMemo(() => fn, [deps])
const memoizedValue = useMomo (
	() => {
    //연산량이 높은 작업을 수행하여 결과를 반환
    return computeExpensiveValue(의존성 변수1, 의존성 변수2);
    },
    [의존성 변수1, 의존성 변수2]
);

렌더링이 일어나는 동안 실행된다.

useMemo( ) 훌을 사용할 떄 기억해야 할 점은
useMemo( )로 전달된 함수는 렌더링이 일어나는 동안 실행된다는 점이다.
그렇기 때문에 일반적으로 렌더링이 일어나는 동안 실행돼서는 안될 작업을 함수에 넣으면 안된다.


예를 들면 useEffect( ) 훅에서 실행돼야 할 사이드 이펙트 같은 것이 있다.
서버에서 데이터를 받아오거나 수동으로 DOM을 변경하는 작업 등은
렌더링이 일어나는 동안 실행돼서는 안되기 때문에 useMemo( )훅의 함수에 넣으면 안되고
useEffect( )훅을 사용해야한다.

const memoizedValue = useMemo(
  	() => computeExpensiveValue(a, b)
);

또한 위 코드와 같이 의존성 배열을 넣지 않을 경우
렌더링이 일어날 때마다 매번 함수가 실행된다.
따라서 useMemo( ) 훅에 의존성 배열을 넣지 않는 것은 아무런 의미가 없다.
그리고 만약 의존성 배열에 빈 배열을 넣게 되면 컴포넌트 마운트 시에만 함수가 실행된다.

useCallback( )

seCallback( )은 useMemo( )훅과 유사한 역할을 한다.
한가지 차이점은 값이 아닌 함수를 반환 한다는 점이다.

의존성 배열에 따라 Memoized 값을 반환한다는 점에서
useMemo( ) 훅과 완전히 동일하다.

useCallback( function, dependencies ) 
useMemo( ( ) => function, dependencies) 

useCallback( ) 선언

useCallback( )훅은 파라미터로 함수,의존성 배열을 받는다.
파마리터로 받는 이 함수를 콜백 함수라고 부른다.

useCallback(fn, [deps])
const memoizedCallback = useCallback(
	() => {
    	doSomething(의존성 변수1, 의존성 변수2);
    },
    [의존성 변수1, 의존성 변수2]
);

useCallback( ) 사용

useCallback( ) 훅을 사용하여 특정 변수의 값이 변한 경우에만 함수를 다시 정의하도록
해서 불필요한 반복 작업을 없애주는 것이다.


import { useState } from "react";

function ParentComponent(props) {
    const [count, setCount] = useState(0);

    //재렌더링 될 때마다 매번 함수가 새로 정의됨
    const handleClick = (event) => {
        //클릭 이벤트 처리
    };

    return (
        <div>
            <button onClick={() => {
                setCount(count + 1);
            }}
            >
                {count}
            </button>

            <childComponent handleClick={handleClick} />
        </div>
    );
}

예를 들어 useCallback( ) 훅을 사용하지 않고 컴포넌트 내에서 정의한 함수를
자식 컴포넌트에 props로 넘겨 사용하는 경우,
부모 컴포넌트가 다시 렌더링 될 때마다 매번 자식 컴포넌트도 다시 렌더링 된다.

import { useState, useCallback } from "react";

function ParentComponent(props) {
    const [count, setCount] = useState(0);

    // 컴포넌트가 마운트 될 때만 함수가 정의됨
    const handleClick = useCallback((event) => {
        //클릭 이벤트 처리
    }, []);

    return (
        <div>
            <button onClick={() => {
                setCount(count + 1);
            }}
            >
                {count}
            </button>

            <childComponent handleClick={handleClick} />
        </div>
    );
}

하지만 useCallback( ) 훅을 사용하면 특정 변수의 값이 변한 경우에만 함수를 다시 정의하게 되므로,
함수가 다시 정의되지 않는 경우에 자식 컴포넌트도 재렌더링이 일어나지 않는다.
이 경우에는 의존성 배열에 빈배열이 들어갔기 때문에,
컴포넌트가 처음 마운트되는 시점에만 함수가 정의되고
이후에는 다시 정의되지 않으며 결국 다시 컴포넌트도 불필요하게 재렌더링이 일어나지 않는다.

0개의 댓글