[react] 성능 개선2

들블리셔·2022년 9월 21일
0

컴포넌트가 재렌더링되면 거기 안에 있는 자식컴포넌트는 항상 함께 재렌더링 된다.

그런데 그 자식컴포넌트가 별거 없이 가벼운 코드라면 크게 상관이 없지만, 굉장히 무거워서 함께 렌더링 시간이 몇초씩이나 걸린다고 생각해보면?

부모 컴포넌트가 재렌더링 될 때마다 원하지 않는 자식컴포넌트가 재렌더링 되서 성능저하를 일으킬 수 있다.




memo

개선 전

import { useState } from 'react'
function Parents() {
  	let [test, setTest] = useState(0);
	return (
    	<Child />
      	<button onClick={ () => { setTest(test + 1) } }></button>
    )
}
function Child() {
  	console.log('나 자식인데 나까지 재렌더링 돼')
	return(
    	<div>나 자식임</div>
    )
}

부모 컴포넌트에서의 onClick이벤트로 인해서 child까지 재렌더링이 함께 된다. console창이 출력되므로 확인 가능하다.

만약 Child컴포넌트의 렌더링 시간이 몇초가 걸리는 컴포넌트라고 하면 심각한 성능저하를 불러온다.


개선 후

import { useState, memo } from 'react'
function Parents() {
  	let [test, setTest] = useState(0);
	return (
    	<Child />
      	<button onClick={ () => { setTest(test + 1) } }></button>
    )
}
let Child = memo( () => {
	console.log('나 자식인데 나까지 재렌더링 돼')
  	return(
    	<div>나 자식임</div>
    )
})

재렌더링을 막기 위해서 memo함수를 사용했다.

최초 렌더링 됐을 때 한 번을 제외하고 더이상 부모컴포넌트의 버튼을 클릭해도 console창이 출력 되지 않으므로 재렌더링이 되지 않는다는 것을 확인할 수 있다.

주의할 점은 memo함수는 props가 변할때만 재렌더링이 되도록 만들었다.

그렇기 때문에 props == props인지에 따라서 변하지 않았으면 재렌더링 하지 않고, props가 변했다면 재렌더링이 된다.

만약 props가 길고 복잡한 코드라면 비교하는 시간이 더 걸리기 때문에 오히려 더 큰 성능저하를 불러올 수 있다.

ex) 아래와 같이 props 사용 시

function Parents() {
  	let [test, setTest] = useState(0);
	return (
    	<Child test={test}/>
      	<button onClick={ () => { setTest(test + 1) } }></button>
    )
}

사실 memo는 사용할 일이 거의 없다고 한다.





useMemo

컴포넌트가 렌더링 될 때 불필요한 컴포넌트까지 리렌더링 되지 않게 하기 위해서 사용하는 memo와 비슷하지만 다른 useMemo

비교적 많이 사용한다.

개선 전

function Parents() {
    let result = Child();
    return (
      	<div>{result}</div>
    )
}
function Child() {
  	console.log('나까지 렌더링 돼')
    return (
        <div>반복문 1억번 돌린 코드라고 가정</div>
    )
}



개선 후

import { useMemo } from 'react'
function Parents() {
    let result = useMemo( () => {
      return Child()
    }, []) 
    return (
      	<div>{result}</div>
    )
}
function Child() {
    console.log('나까지 렌더링 돼')
    return (
        <div>반복문 1억번 돌린 코드라고 가정</div>
    )
}

반복문 결과를 return한 Child컴포넌트를 변수에 담아서 사용 하고싶다고 가정했을시

최초 렌더링했을 때 한 번을 제외하고선 result가 재렌더링 되지 않는다.

useEffect처럼 두 번째 인자에 dependency를 활용 할 수있다.
useEffect의 형태와 작동 원리도 같다.

dependency자리에 state를 넣는다면 그 state가 변함에 따라 재렌더링이 될 수는 있다.



useEffect와 useMemo의 차이

이렇게 보면 useEffect와 다른 부분이 하나도 없다. 그런데도 불구하고 왜 useMemo를 사용해야 하는가?

두 가지의 다른점은 그냥 실행시점 차이이다.

useEffect에서 전달된 함수는 return() 안의 html코드가 실행이 끝나면 실행되고, 즉 렌더링 중에서 실행 되지 않는다.

useMemo에서 전달된 함수는 렌더링 중 실행한다. return() 안이 렌더링 될 떄 같이 된다는 말이다.






결론

memo든 useMemo든
꼭 부모,자식의 상관관계가 아닌 어떤 컴포넌트가 렌더링 될때 다른 해당 컴포넌트에서 사용 되는 다른 컴포넌트도 재렌더링 되는 것을 방지하기 위해서 사용한다.

다만 차이점은
memo는 컴포넌트를 감싸서 props가 바뀌었을 때만 리렌더링 되고,
useMemo는 모든 값을 캐싱할 수 있다.

profile
나의 공부방

0개의 댓글