react 렌더링 최적화

악음·2021년 12월 6일
0

react.js

목록 보기
5/11
post-thumbnail

참고한 싸이트
https://cocoder16.tistory.com/36

state는 어디서 선언해야 하나?

state가 변하면 일어나는일

  1. 해당 state가 선언된 함수(컴포넌트)가 재실행된다.
  2. 때문에 하위에 있는 모든 컴포넌트가 리렌더링된다.
  3. 이과정에서 해당 스테이트에 영향을 받지 않는 컴포넌트들의 '불필요한'리렌더링이 일어난다.

때문에 state는 자신이 필요한 컴포넌트에서 선언되어야한다
만약 index.js에 선언되었다고 하면 해당 스테이트가 변경될때마다 전체 컴포넌트가 리렌더링 될것이다.
때문에 적합한 위치에선언해야한다

또한 한개의 스테이트에 여러 컴포넌트에 쓰이는 오브젝트를 넣어선 안된다.

const [state,setState]=useState({
	component1Props:"난 컴포넌트 1에만씀",
  	component2Props:"난 컴포넌트 2에만씀"
})

위와 같은 스테이트가 있다는 가정하에 component1으로 넘겨진 props을 변경하기위해 seState를 한다고하면 component2에 값은 변경되지 않았지만 같이 렌더링이 될것이다.
때문에 자식 component에 넘겨줄 state를 각각 만들어야 할것이다.

각각 선언한다고해도 어차피 스테이트가 바뀔때마다 자식 컴포넌트가 리렌더링 되니 필요없는 일이 아닌가?
라는 의문이 들었다면 그 궁금증에 대한 해소는 다음 파트에서 넘기도록 한다.

그럼에도 불필요한 리렌더링이 일어나는 경우

위에 설명처럼 state가 필요한 부분에서 선언이 되거나
각각 선언해도 불필요한 리렌더링은 해소할수없다.
때문에 react에선 다음과같은 hook/기능을 제공해준다.

  1. React.memo
  2. key
  3. useCallBack
  4. useMemo

1. React.memo

React.memo의 사용법

function WrapingComponent(props){
	return (<div>{props.component1Props}</div>)
}

export React.memo(WrapingComponent)

이런식으로 컴퍼넌트를 감싼다면 해당 컴포넌트에 전달된 prop이 바뀌기 전까지 리렌더링이 되지 않는다.
때문에 처음 말했던 각각 컴포넌트에 전달하는 state는 따로 선언되어야한다
(한 스테이트안에 오브젝트로 여러 콤포넌트에 전달 될 값이 있다면 유즈 메모를 쓰는 의미가없다)

2. key

많은 react 유저들은 컴포넌트의 key를 index로 주지말라는 warning을 봤을것이다
index도 유니크한데 왜 index으로 주지말라는 것일까?
키란?(react.org)
위에 싸이트를 보면 react아 어떤 항목을 변경, 추가, 삭제 할지 식별하는 것을 돕는다고 되어있다.
그럴려면 고유성이 필요하다(어떤 키값의 데이터를 변경할것인지 알려주어야하기때문)

하지만 index으로 줄경우 베열 state가 삭제되거나 어떤 값이 추가될경우 index가 자동으로 바뀌게 되므로 다시 index를 할당하면서 리마운트가 일어나게된다. 때문에 고유 값으로 지정해주어야한다.

3. useMemo

특정 자식 컴포넌트 내부에 시간이 오래걸리는 함수의 리턴값을 사용하는 변수가 있다고 하자
그렇다면 그 컴포넌트는 리렌더링 할때마다 시간이 오래걸리는 함수를 한번더 리렌더링 시킬 것이다
때문에 useMemo를 사용하여 뎁스의 값이 바뀌기 전까진 반환된 값을 재사용한다.

function useMemoComponent(props){
	const memoValue=useMemo(()=>{
      let value=""
      // 시간이 오래걸리는 함수의 코드
      return value
      
      // 아레 뎁스가 바뀌지 않는경우 다시는 해당 함수가 실행되지 않고 반환된 값을 재사용한다.
    },[props.parameter])
  return <div>{memoValue}</div>
}

4. useCallBack

useCallback도 비슷한 맥락으로 사용할수 있다.
함수는 컴포넌트가 리렌더링 되면 다시 생성된다 따라서 해당 함수를 props으로 받는 자식 컴포넌트도 리렌더링된다. 이럴 경우를 대비하여 useCallBack을 사용하면 해당 뎁스가 바뀌지 않는이상 재생성하지 않고 이전에 있던 함수를 그대로 넘겨주기때문에 리렌더링이 방지가된다.

function haveCallbackComponent (){
	const callBack=useCallback(()=>{
      // 자식에 전달될 함수 코드
      
      //아래 값이 바뀌기 전엔 리렌더링이 일어나지 않는다.
    },[state1])
}
return <ChildComponent callBack={callBack}  />

정리

리엑트에 사용되는 state는 위에서 아래로 흐른다.
때문에 아래로 흐를수록 더욱더 많은 콤포넌트들이 존재하기때문에 불필요한 리렌더링이 많아질것이고
이것을 방지하고자 useMemo나 useCallback useMemo를 사용하라고 한다 하지만 react에선 정말 비싼 계산(expensiveCompute)에 사용하도록 하고있다.
이부분을 정확히 측정하고 싶다면프로파일을 공부하고 이용해보자 이러한 과정을 통해 메모이제이션을 써서 얻는 이점이 있다면 사용하고 그렇지 않다면 사용하지 않아도 무방하다고생각한다.

profile
RN/react.js개발자이며 배운것들을 제가 보기위해서 정리하기 때문에 비속어 오타가 있을수있습니다.

0개의 댓글