그동안 진행하였던 익명게시판 프로젝트를 최적화해보도록 하자.
React.memo()
를 이용하여, 랜더링이 필요 없는 부분도 랜더링되는것을 방지하는 것입니다.
일단 개발자 도구의 확장 프로그램을 사용하여 Profiler
를 클릭한다. ShowPost
부분이 어느 부분에서 비효율적일까? 체크해보자.
render가 어떻게 이루어지는지 확인 가능하다. 댓글을 작성해보자.
댓글을 작성해 보았고, 변경된 부분은 우리가 형광펜으로 칠해둔 부분뿐이다. 그런데 글 보는 부분이나, 기존에 작성된 댓글들도 랜더가 다시 된다. ShowPost에 있다는 이유 하나로 다른 친구들까지 모두 re-render가 된 것이다.
필요한 부분만 랜더가 되도록 바꾸어보자.
<PostTitleDiv>
<PostTitle>{post && post.title}</PostTitle>
</PostTitleDiv>
{postLoading ? (
<LoadingDiv>
<LoadingImg src={`${process.env.PUBLIC_URL}/img/loading.svg`} />
</LoadingDiv>
) : (
<PostReplDiv>{post && post.contents}</PostReplDiv>
)}
{/* post contents */}
<ReplTitleDiv>댓글 {replCount} </ReplTitleDiv>
{replLoading ? (
<LoadingDiv>
<LoadingImg src={`${process.env.PUBLIC_URL}/img/loading.svg`} />
</LoadingDiv>
) : (
repls &&
repls.map((element) => (
<PostReplDiv key={element}>
<ReplWriter>익명</ReplWriter>
<Repl>{element}</Repl>
</PostReplDiv>
))
)}
<WriterDiv>
<ReplInput
onChange = {onChange}
value = {repl}
ref = {replInput}></ReplInput>
<ReplSubmitDiv onClick = {onSubmitRepl}>
<span>입력</span>
</ReplSubmitDiv>
</WriterDiv>
해당 부분을 밖으로 빼서, memo해줍시다! 일단 그러한 함수를 만들기 위해서 해당 부분을 빼와 다음과 같이 코드를 작성한다.
const PostAndRepl = () => {
return(
<>
<PostTitleDiv>
<PostTitle>{post && post.title}</PostTitle>
</PostTitleDiv>
{postLoading ? (
<LoadingDiv>
<LoadingImg src={`${process.env.PUBLIC_URL}/img/loading.svg`} />
</LoadingDiv>
) : (
<PostReplDiv>{post && post.contents}</PostReplDiv>
)}
{/* post contents */}
<ReplTitleDiv>댓글 {replCount} </ReplTitleDiv>
{replLoading ? (
<LoadingDiv>
<LoadingImg src={`${process.env.PUBLIC_URL}/img/loading.svg`} />
</LoadingDiv>
) : (
repls &&
repls.map((element) => (
<PostReplDiv key={element}>
<ReplWriter>익명</ReplWriter>
<Repl>{element}</Repl>
</PostReplDiv>
))
)}</>)
}
그런데 문제점이 있죠. 우리가 가지고 있지 않은 변수들이 있기 때문!!
이것들을 props로 전달해주어야 진정으로 완료되는 것이다~
그리고 React.memo
로 감싸주실게요~
const PostAndRepl = React.memo( ({post,postLoading,replLoading,repls,replCount}) => {
return(
<>
<PostTitleDiv>
<PostTitle>{post && post.title}</PostTitle>
</PostTitleDiv>
{postLoading ? (
<LoadingDiv>
<LoadingImg src={`${process.env.PUBLIC_URL}/img/loading.svg`} />
</LoadingDiv>
) : (
<PostReplDiv>{post && post.contents}</PostReplDiv>
)}
{/* post contents */}
<ReplTitleDiv>댓글 {replCount} </ReplTitleDiv>
{replLoading ? (
<LoadingDiv>
<LoadingImg src={`${process.env.PUBLIC_URL}/img/loading.svg`} />
</LoadingDiv>
) : (
repls &&
repls.map((element) => (
<PostReplDiv key={element}>
<ReplWriter>익명</ReplWriter>
<Repl>{element}</Repl>
</PostReplDiv>
))
)}</>)
})
짠! 감싸서 완성입니다요 :) 이제 어떻게 랜더되었는지 한번 확인해보죠.
신기한 현상이에요! 저희가 memo한부분은 랜더되지 않았습니다. :)
이렇게 불필요한 render를 줄여, 최적화를 할 수 있습니다!
내친김에 footer, Slogon도 memo해봅시당!
이 친구는 조금 더 간단한 방법을 사용하였다.
footer.jsx
import React from 'react';
import {
FooterDiv,
FooterSmall,
FooterBig,
} from './styledComponent';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faReact } from '@fortawesome/free-brands-svg-icons';
function Footer(){
return (
<FooterDiv>
<FontAwesomeIcon icon = {faReact} />
<FooterBig>for react study</FooterBig>
<FooterSmall>2022.by Eugene</FooterSmall>
</FooterDiv>
)
}
export default React.memo(Footer);
slogon.jsx
import React from 'react';
import {
SlogunBig,
SlogunSection,
SlogunSmall,
} from './styledComponent';
function Slogun(){
return (
<SlogunSection>
<SlogunBig>자유롭게 의견을 나누어요</SlogunBig>
<SlogunSmall>악플은 금물!</SlogunSmall>
</SlogunSection>
)
}
export default React.memo(Slogun);
위와 같이 re-render되지 않음을 알 수 있따!