Memoization?

컴퓨터에서 동일한 계산을 반복할 때, 이전에 계산된 값을 메모리에 저장함으로써 동일 반복 계산을 제거하여 속도를 빠르게 하는것이다.

(wikipedia 참조)

https://ko.wikipedia.org/wiki/메모이제이션

메모이제이션 - 위키백과, 우리 모두의 백과사전 위키백과, 우리 모두의 백과사전. 메모이제이션(memoization)은 컴퓨터 프로그램이 동일한 계산을 반복해야 할 때, 이전에 계산한 값을 메모리에 저장함으로써 동일한 계산의 반복 수행을 제거하여 ko.wikipedia.org

React.memo

동일한 props로 렌더링을 한다면, React.memo를 사용하여 성능 향상을 누릴 수 있다.

memo를 사용하면 React는 컴포넌트를 렌더링하지 않고 마지막으로 렌더링된 결과를 재사용합니다.

실습

<Memo.jsx>

먼저 CommentList를 map으로 순환하여 props로 넣어 렌더링 하는 간단한 예시를 작성해보았다.

useEffect를 사용하여 2초마다 새로운 Comment를 생성하게 해주었다.

import React, { useState, useEffect } from 'react'
import Comments from './Comments'

const CommentList = [
  { title: 'comment1', content: 'message1', likes: 1 },
  { title: 'comment2', content: 'message2', likes: 1 },
  { title: 'comment3', content: 'message3', likes: 1 },
]

export default function Memo() {
  const [comments, setComments] = useState(CommentList)

  useEffect(() => {
    const interval = setInterval(() => {
      setComments(prevComment => [
        ...prevComment,
        {
          title: `comment${prevComment.length + 1}`,
          content: `message${prevComment.length + 1}`,
          likes: prevComment.length + 1,
        },
      ])
    }, 2000)

    return () => {
      clearInterval(interval)
    }
  }, [])

  return <Comments commentList={comments} />
}

<Comments.jsx>

여기서는 props로 받은 CommentList를 map()으로 CommentItem에 전달해주는 컴포넌트를 만들었다.

import React, { useCallback } from 'react'
import CommentItem from './CommentItem'

export default function Comments({ commentList }) {
  return (
    <div>
      {commentList.map(comment => (
        <CommentItem
          key={comment.key}
          title={comment.title}
          content={comment.content}
          likes={comment.likes}
        />
      ))}
    </div>
  )
}

<CommentItem.jsx>

Comments에서 전달받은 props를 실제로 그리게 하였다.

import React, { Profiler, memo, useMemo, useState } from 'react'
import './CommentItem.css'
import { click } from '@testing-library/user-event/dist/click'

function CommentItem({ title, content, likes, onClick }) {
  const [clickCount, setClickCount] = useState(0)
  function onRenderCallback(
    id,// 방금 커밋된 Profiler 트리의 "id"
    phase,// "mount" (트리가 방금 마운트가 된 경우) 혹은 "update"(트리가 리렌더링된 경우)
    actualDuration,// 커밋된 업데이트를 렌더링하는데 걸린 시간
    baseDuration,// 메모이제이션 없이 하위 트리 전체를 렌더링하는데 걸리는 예상시간
    startTime,// React가 언제 해당 업데이트를 렌더링하기 시작했는지
    commitTime,// React가 해당 업데이트를 언제 커밋했는지
    interactions// 이 업데이트에 해당하는 상호작용들의 집합
  ) {
// 렌더링 타이밍을 집합하거나 로그...console.log(`actualDuration(${title} : ${actualDuration})`)
  }

  return (
    <Profiler id="CommentItem" onRender={onRenderCallback}>
      <div className="CommentItem">
        <span>{title}</span>
        <br />
        <span>{content}</span>
        <br />
        <span>{likes}</span>
      </div>
    </Profiler>
  )
}

export default memo(CommentItem)

memo를 사용할 경우 새로 생성하는것만 그리는 것을 확인할 수 있다.