본문 바로가기

개발 지식

[React] useEffect vs useMemo vs useCallback

🤓 시작하며 

지난 면접에서 useMemo와 useCallback, 그리고 useEffect의 차이를 물어봤었는데 정확하게 대답을 하지 못해 굉장히 당황했던 적이 있었다. 사실 useEffect는 주구장창 써왔기 때문에 자신이 있었지만 useMemo, useCallback은 그 필요성을 느끼지 못했기 때문에 굳이 쓰지 않았었다. 하지만 리액트가 불필요한 훅을 만들리가 없으니.. 이참에 각각의 특징과 어떤때에 쓰면 좋은지 알아보려 한다.


1️⃣ useEffect

사용 목적

  • 리액트 컴포넌트가 렌더링될 때마다 특정 작업을 실행할 수 있도록 하는 Hook
  • componet가 mount 됐을 때, unmount 됐을 때, update 됐을 때 특정 작업을 처리할 수 있다.
  • 첫번째 인자에는 수행하고자 하는 작업을, 두번째 인자에는 의존성 배열을 넣는다.
useEffect(()=>{}, [])

사용 예시

1. 컴포넌트가 mount 됐을 때

 

  • 컴포넌트가 화면에 처음 렌더링 될 때, 한 번만 실행하고 싶을 때는 빈 배열을 넣는다.
useEffect(() => {
	console.log('마운트 될 때만 실행된다.');
}, []);

 

2. 컴포넌트가 update 될  때

  • 특정값이 업데이트 될 때 실행하고 싶을 경우, 배열 안에 검사하고 싶은 값을 넣어준다.
  • 업데이트 될 때만 실행하는 것이 아니라 마운트 될 때도 실행된다.
useEffect(() => {
	console.log(name);
	console.log('업데이트 될 때만 실행된다.');
}, [name]);

 

3. 컴포넌트가 unmount 될 때 or update 되기 직전에

  • cleanup 함수 반환 -> return 사용
  • unmount 될 때만 cleanup 함수를 실행하고 싶을 경우, 두 번째 파라미터로 빈 배열을 넣는다.
  • 특정 값이 업데이트되기 직전에 cleanup 함수를 실행하고 싶을 때 배열 안에 검사하고 싶은 값을 넣어준다.
useEffect(() => {
	console.log('effect');
	console.log(name);
	return () => {
		console.log('cleanup');
		console.log(name);
	};
}, []);

 

 

2️⃣ useCallback

사용 목적

  • 메모이제이션된 함수를 반환하는 Hook
  • 메모이제이션 : 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술
  • 첫번째 인자에는 수행하고자 하는 작업을, 두번째 인자에는 의존성 배열을 넣는다.
useCallback(() => {}, []);

사용 예시

  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]); // count가 변경되면 함수가 다시 생성되고, 그렇지 않으면 이전에 생성된 함수를 사용

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={handleClick}>Increment</button>
    </div>
  );

 

  • useCallback을 사용하면 handleClick 함수가 계속 새로 만들어지는 것을 방지할 수 있다.
  • count가 변경될 때만 새로운 함수를 만들고, 그렇지 않을 경우엔 (메모이제이션된) 동일한 함수를 불러온다.
  • 자식 컴포넌트에 함수를 props로 넘겨줄 때, (자식 컴포넌트의) 불필요한 렌더링을 방지할 수 있다.

 

3️⃣ useMemo

사용 목적

  • 메모이제이션된 값을 반환하는 Hook
  • 첫번째 인자에는 수행하고자 하는 작업을, 두번째 인자에는 의존성 배열을 넣는다.
useMemo(() => {}, []);

사용 예시

const [a, setA] = useState(0);
  const [b, setB] = useState(0);

  // a와 b가 변경될 때마다 sum을 다시 계산하지 않고, 이전에 계산된 값을 재사용
  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return a + b;
  }, [a, b]);

  return (
    <div>
      <p>a: {a}</p>
      <p>b: {b}</p>
      <p>Sum: {sum}</p>
      <button onClick={() => setA(a + 1)}>Increment a</button>
      <button onClick={() => setB(b + 1)}>Increment b</button>
    </div>
  );
  • useMemo 함수가 값을 저장해두고 있다가 a 또는 b가 변경될 때만 복잡한계산함수를 실행시켜 메모이제이션된 값을 업데이트 해준다.

 


 

 

✏️ 마치며

useCallback과 useMemo 모두 성능 최적화를 위해 사용되는 hook 이다. 예시처럼 간단한 함수나 계산이 아닌 복잡한 계산이 들어갔을때 그 효과를 더 극적으로 볼 수 있을 것 같다. 다음 프로젝트에는 useCallback과 useMemo를 좀 더 적극적으로 사용해서 개념을 확실하게 알 수 있도록 해야겠다..!