[React] 익명게시판 최적화하기

김유진·2022년 7월 7일
1

React

목록 보기
16/64

그동안 진행하였던 익명게시판 프로젝트를 최적화해보도록 하자.
React.memo()를 이용하여, 랜더링이 필요 없는 부분도 랜더링되는것을 방지하는 것입니다.

1.ShowPost 최적화하기

일단 개발자 도구의 확장 프로그램을 사용하여 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되지 않음을 알 수 있따!

0개의 댓글