컴퓨터에서 동일한 계산을 반복할 때, 이전에 계산된 값을 메모리에 저장함으로써 동일 반복 계산을 제거하여 속도를 빠르게 하는것이다.
(wikipedia 참조)
https://ko.wikipedia.org/wiki/메모이제이션
동일한 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를 사용할 경우 새로 생성하는것만 그리는 것을 확인할 수 있다.