📚 프론트엔드 공부 일지/REACT

React 최적화 Hook (React.memo / useCallback / useMemo)

wei3on 2024. 7. 25. 12:16

 

최적화?

성능 최적화를 왜 할까?
-> 불필요한 렌더링을 방지하기 위해서

소규모 프로젝트에서는 큰 손실이 없을지 모르지만 프로젝트가 커질수록

쓸모없는 렌더링이 메모리를 사용해 속도를 느리게 만들것이고 사용자 경험에도 영향을 미치게 됨

 

개념

"리액트의 최적화" = "렌더링을 최적화 하는것"

 

렌더링 개념

리액트에서 컴포넌트가 렌더링을 언제 수행하나?
1. Props가 변경될때
2. State가 변경될때
3. forceUpdate() 를 실행했을때
4. 부모 컴포넌트가 렌더링 되었을때 자식 컴포넌트도 렌더링됨

 

*참고 :렌더링 과정에서 변수나 함수는 초기화 된다.

 

 

 

React.memo(), useCallback, usememo 모두 memoization 개념 사용

? Memoization
비용이 많이 드는 함수 호출의 결과를 저장하고 동일한 입력이 다시 발생 할 때
캐시된 결과를 반환하여 프로그램의 속도를 높이는데 주로 사용되는 최적화 기술

 

React.memo()

 

자신의 props가 바뀔 때만 리렌더링 되는 고차 컴포넌트를 반환하는 함수

* 고차 컴포넌트: 컴포넌트를 받아 새 컴포넌트를 반환하는 함수

 

컴포넌트가 동일한 props로 동일한 결과를 렌더링 하면

React.memo는 마지막으로 렌더링 된 결과를 재사용

 

const MyComponent = React.memo(function MyComponent(props) {
  /* props를 사용하여 렌더링 */
});

function MyComponent(props) {
  /* props를 사용하여 렌더링 */
}
function areEqual(prevProps, nextProps) {
  /*
  nextProps가 prevProps와 동일한 값을 가지면 true를 반환하고, 그렇지 않다면 false를 반환
  */
}
export default React.memo(MyComponent, areEqual);

 

useCallback

 

"함수"를 기억하고 재사용한다.

리랜더링시 재생성 되는 함수

하지만 useCallback을 사용해서 콜백함수를 메모리에 저장하고 재사용 할 수 있다.

 

 

React.memo() 를 통해서 컴포넌트의 성능을 높여줬다면

 

함수에는 메모이제이션된 함수를 반환하는 함수인 useCallback을 적용시켜줌

 

const List = React.memo(({posts}) => {
  console.log("List component is randering")
  return (
    <ul>
      {posts.map(post => {
        return(
          <ListItem  key={post.id} post={post}/>
        )
      })}
    </ul>
  )
})

const B = ({message, posts}) => {
  console.log("B component is randering")

  const testFunction =() => {}
  return (
    <div>
      <h1>B Component</h1>
      <Message message={message}/>
      <List  posts={posts} testFunction={testFunction}/>
    </div>
  )
}

export default B

 

이렇게 하면 B컴포넌트가 재랜더링 될 때,

자식 컴포넌트인 List에 props로 내려주는게 있기 때문에 (posts, testFunction)

List까지 계속 재랜더링 되게 됨

 

const testFunction = () => {
	useCallback(() => {}, [])
}

// useCallback으로 감싸준 후 첫번째 인수에 콜백 함수
// 두번째 인수에 의존성 배열 []

 

의존성 배열 내부 값이 변경 되면 testFunction은 새로 만들어진 함수 객체로 초기화

그렇지 않으면, 동일한 함수 리턴

 

자식 컴포넌트에 useCallback을 사용하면

계속 자식 컴포넌트가 리랜더링 되는 상황을 막을 수 있음

 

 


 

useMemo

"값"을 기억한다.

component는 state가 변하면 리렌더링을 한다.

값이 변경되지 않았는데 리렌더링 되는 것은 불필요하기 때문에 useMemo를 통해 최적화 할 수 있음

 

function Component({a, b}) {
	const result = compute(a, b)
    return <div>{result}</div>
}

 

Component내의 compute 함수가 만약 복잡한 연산을 수행하면

결과 값을 리턴하는데 오랜시간이 걸림

 

▶ 이때, 컴포넌트가 계속 리랜더링 되면 연산을 계속 수행하는데 오랜시간이 걸려서

     성능에 안좋은 영향을 미치게 되고 UI 지연 현상도 일어나게 됨

 

❗️ 이런 현상을 useMemo로 해결!

compute 함수에 넘겨주는 a, b의 값이 이전과 동일하면,

컴포넌트가 리랜더링 되더라도 연산을 다시 하지 않고 이전 랜더링 때 저장해두었던 값 재활용

 

function Component({a, b}) {
	const result = useMemo(() => {compute(a, b)}, [a, b])
    return <div>{result}</div>
}
// useMemo로 감싸주고 첫번째 인수에 콜백 함수
// 두번째 인수로 의존성 배열

 

의존성 배열 안에 있는 값이 업데이트 될 때만 콜백 함수를 다시 호출하여

메모리에 저장된 값을 업데이트

function Component({a, b}) {
	const result = useMemo(() => {compute(a, b)}, [])
    return <div>{result}</div>
}

 

만약 두번째 인수에 빈 배열을 넣는다면

마운트 될 때만 값을 계산하고 그 이후론 계속 메모이징 된 값을 꺼내와 사용

'📚 프론트엔드 공부 일지 > REACT' 카테고리의 다른 글

이미지 레이지 로딩  (0) 2024.07.30
vite를 이용한 리액트 생성  (1) 2024.07.26
React 확장 프로그램 / Profiler 성능 측정 프로그램  (6) 2024.07.24
React Hooks  (0) 2024.07.19
constructor / super  (0) 2024.07.18