React - useMemo

춤추는개발자·2023년 4월 3일
0
post-thumbnail

Memoization ?
자주 사용하는 값을 처음 코드가 실행될때 계산하고 그 값을 캐싱해 두었다가 필요할때마다 다시 계산하지 않고 캐싱해둔 값을 꺼내서 사용하는 기법을 말합니다.

함수형 컴포넌트는 함수이기 때문에 렌더링이 될 때마다 함수형 컴포넌트를 다시 호출하고 컴포넌트 안의 변수들을 모두 초기화 합니다.

useMemo 를 사용하면 처음 렌더링 될 때만 컴포넌트를 호출했을때 내부 코드를 모두 초기화 또는 호출하고 useMemo 를 사용해둔 코드들은 리 렌더링 될 때 컴포넌트가 다시 호출 되어도 다시 호출되지 않고 처음에 호출했던 값을 그대로 사용하게 됩니다.

useMemo 사용 법

useMemo 는 두개의 인자를 받습니다. 첫번째 인자로는 콜백함수이고 우리가 캐싱할 값을 계산해서 리턴해주는 코드이고, 두번째 인자로는 배열을 받습니다. 배열 안에는 값이 들어가는데 그 값이 바뀌면 콜백함수를 다시 호출해 새로운 반환 값을 받습니다.
빈 배열이라면 컴포넌트가 처음 마운트 되었을때만 값을 계산하고 그 이후에는 필요할때 그 값을 사용합니다.

꼭 기억해둬야 할 값들만 useMemo 를 사용하는것이 메모리를 낭비하지 않는 방법입니다.

useMemo 사용 예

useMemo 의 강력한 장점을 소개할려고 합니다. useMemo 를 아주 복잡하고 오래걸리는 작업을 하는 함수를 한번만 진행하고 그 이후에는 반환 값을 저장해뒀던 값을 가지고 와서 사용하는 예가 대표적인 예라고 할 수 있습니다.
요번 시간에는 또 다른 예를 소개 할려고 합니다.

나이와 국적을 물어보는 프로그램을 만들었습니다.

여기서 이름과 국적을 선택하면 화면에 입력한 이름과 클릭한 국적이 화면에 보여지는 프로그램 입니다. 아주 간단하죠.

저는 이름은 kane 국적은 외국을 선택 했습니다. 입력한대로 결과가 잘 나오는것을 확인할 수 있습니다.

이 프로그램의 코드를 보시면

const App = () => {
  const [name, setName] = useState('');
  const [nation, setNation] = useState('');

  const onchange = (e) => {
    console.log(typeof e.target.value);
    setName(e.target.value);
  };

  const nations = {
    result: nation === '' ? '' : nation === '한국' ? '한국' : '외국',
  };

  useEffect(() => {
    console.log('nations 변경!');
  }, [nations]);

  const onclickButton = (e) => {
    setNation(e.target.textContent);
  };

  return (
    <>
      <span>당신의 이름은 무엇입니까?</span>
      <div>
        <input
          type="text"
          placeholder="이름을 입력하세요."
          value={name}
          onChange={onchange}
        />{' '}
        {name !== '' && <span> 당신의 이름은 {name} 이군요. </span>}
      </div>
      <span>당신의 국적은 어디 입니까?</span>
      <button onClick={onclickButton}>한국</button>
      <button onClick={onclickButton}>외국</button>

      {nations.result !== '' && (
        <span>{nations.result} 사람 이시군요 반갑습니다!</span>
      )}
    </>
  );
};

저는 국적 버튼을 클릭하면 nations 객체에 국적이 저장되고 클릭한 국적에 따라서 nations 객체의 result 프로퍼티의 값이 변경되고 result 의 값이 화면에 보여지도록 코드를 작성 하였습니다.
그리고 위의 프로그램 코드에서 useEffect 를 사용해서 어떤 작업을 한다고 생각 해봅시다. 그리고 nations 의 값이 바뀌면 useEffect 의 콜백함수는 리 렌더링 되면서 다시 실행된다고 해봅시다.

처음 컴포넌트가 렌더링 되면 당연히 useEffect 의 콜백함수가 실행 되겠죠.
그리고 이름을 입력 해봅시다.

kane 이름을 입력했는데 useEffect 의 콜백함수가 실행된것을 확인 할 수 있습니다.
엥? 저희는 분명 dependency array 에 nations 의 값이 변경되면 useEffect 의 콜백함수를 실행하도록 코드를 작성하였는데 이게 뭘까요.

이렇게 된 이유는 이름을 입력하면서 컴포넌트가 리 렌더링 될때 컴포넌트 내부의 변수가 초기화 되면서 nations 에 저장되는 객체의 주소가 재 할당 되었기 때문에 React 는 nations 의 값이 바뀌었다고 생각해 useEffect 의 콜백함수를 실행한 것 입니다.

이때 우리는 useMemo 를 사용해 nation 스테이트가 변경되지 않으면 객체를 재할당 하지 않고 반환 받은 객체를 기억하도록 할 것 입니다.

  const nations = useMemo(() => {
    return {
      result: nation === '한국' ? '한국' : '외국',
    };
  }, [nation]);

nations 의 코드를 useMemo 로 감싸고 첫번째 인자로는 콜백함수로 객체를 반환 해주고 두번째 인자로는 nation 이 담긴 배열을 전달 합니다.

이렇게 해주면 처음 렌더링 될때 useEffect 의 콜백함수가 실행된 것 빼고는 이름을 입력해도 useEffect 의 콜백함수가 실행되지 않는것을 확인 할 수 있습니다.

이렇게 컴포넌트 안에 객체 값을 가지는 변수가 있다면 useMemo 를 통해서 배열의 값이 바뀔때만 객체가 재 할당 되도록 할 수 있습니다.

0개의 댓글