본문 바로가기
React

useMemo를 사용한 성능 최적화

by @kkkk_biiin 2023. 11. 27.
728x90

useMemo

 리액트에서 컴포넌트의 성능을 최적화하기 위해 사용하는 훅이다. Memo는 Memoization을 의미하며, 동일한 데이터를 반복적으로 요청을 할 때  맨 처음값을 메모리에 저장해서 필요할 때마다 값을 계산하지 않고 메모리에서 꺼내서 사용하는 기법이다. 즉, 컴포넌트가 리렌더링이 됐을 때 데이터를 다시 계산하지 않고 메모리에 저장된 것을 가져오는 것을 의미한다.

 

 useMemo의 구조는 메모이제이션 해줄 값을 계산해서 리턴해주는 콜백함수와, 배열의 값이 업데이트될 때만 실행할 수 있도록 해주는 의존성 배열로 구성되어 있으며, 아래와 같다.(밑에 실제 사용 코드 있음)

 

const value = useMemo(() => {
   return calculate()	// 콜백함수
}, [item])		// 의존성 배열

 

 

 실제로 리액트 컴포넌트에서 복잡한 연산(for문의 for문의 ... 등)을 하는 경우는 많이 없기 때문에 연산한 값을 저장하는 데 많이 사용하지는 않는다. 그렇다면 언제 사용하는 것이 좋을까?

 

 객체 타입을 저장하고 이 값을 Memoization 하고자 할 때 사용하는 것이 좋다. 객체 타입은 원시타입과는 다르게 메모리의 주소값을 저장하기 때문에 렌더링이 일어났을 때 객체를 저장한 메모리의 주소값이 변경이 되기 때문이다. 

원시(Primitive) 타입: String, Number, Boolean, Null, Undefined
객체(Object) 타입: 원시 타입을 제외한 모든 것(Object, Array ... )

 

 

 아래의 코드에서는 useEffect가 [location]이라는 의존성 배열을 가지고 있기 때문에 location의 값이 변경됐을 때만 호출이 돼야 한다. 하지만 number의 값이 변경이 돼도 useEffect가 호출이 되는데, 이유는 number의 값이 변경되면서 렌더링이 발생하고, 이에 따라 location의 주소값도 변경이 되기 때문에 리액트에서는 location의 값이 변경됐다고 인식하는 것이다. 따라서 이러한 경우에 location의 값을 Memoization 하여 location의 값이 초기화 되는 것을 막아줄 수 있다.

 

// number의 값이 변경될 때 useEffect도 같이 호출이 됨(useMemo 사용 x)
function App() {
  const [number, setNumber] = useState(0)
  const [isKorea, setIsKorea] = useState(true)
    
  const location = {
    country: isKorea ? '한국' : '외국'
  }
    
  useEffect(() => {
    console.log('useEffect 출력')
  }, [location])

 

 

 따라서 다음과 같이 useMemo를 사용하여 객체의 값을 저장해서 useEffect 호출을 막을 수 있다.

 

// useMemo 사용
function App() {
  const [number, setNumber] = useState(0)
  const [isKorea, setIsKorea] = useState(true)
    
  const location = useMemo(() => {
    return {
      country: isKorea ? '한국' : '외국'
    }
  }, [isKorea])
    
  useEffect(() => {
    console.log('useEffect 출력')
  }, [location])

 

 

 useMemo는 불필요한 렌더링을 막아줘서 성능을 높인다는 장점이 있다. 하지만 메모리를 소비하기 때문에 무분별하게 사용할 경우 성능이 오히려 나빠질 수도 있다는 점이 있다. 따라서 무분별하게 사용하는 것은 좋지 않다.

 

 

 

 

Reference
https://www.youtube.com/watch?v=e-CnI8Q5RY4&list=PLZ5oZ2KmQEYjwhSxjB_74PoU6pmFzgVMO&index=6
https://velog.io/@jinyoung985/React-useMemo%EB%9E%80
https://velog.io/@sunkim/React.memo-useMemo-useCallback-%EC%97%AD%ED%95%A0-%EB%B0%8F-%EC%B0%A8%EC%9D%B4%EC%A0%90

 

728x90