[React] 브라우저 렌더링, prefetch, preload

I'm ·2023년 4월 18일

🎨 Call-Tree로 이해하는 CRP(Critical Rendering Path) 브라우저 렌더링

  • 렌더링 시 화면에 렌더해야 하는 요소를 구분하는 작업을 통해
    렌더트리는 최종적으로 브라우저에 표기될 요소들이라고 생각하면 된다.

  • Reflow(Layout)/Repaint(Repaint) 중, 더 오래걸리는 작업은?
    => Reflow(Layout)
    Layout이 변하면 Paint도 다시 해줘야한다.

  • Reflow, Layout의 차이는 브라우저마다 다르게 부르는 것 입니다.

  • Performance 개발자도구 녹화해서 Call Tree에서 Layout, Paint확인

🎨 Reflow(Layout)와 Repaint(Paint)

  • reflow란 렌더링 되어야 할 요소들을 화면상 위치를 그려주는 과정입니다.
  • 그리고 repaint는 위치를 잡고 난 이후 색칠을 해주는 과정입니다.

🎨 reflow & repaint with Board

  • 목록을 조회해올 때, 데이터가 비어있다 나중에 들어와 UI 상으로 데이터를 뿌려주는 부분의 크기가 달라지는 것을 확인할 수 있다.
    이렇게 되면 reflow가 일어나기 때문에 높이를 고정시켜주고 데이터를 받아와 보도록 하겠습니다.
import { gql, useQuery } from "@apollo/client";
import { MouseEvent } from "react";
import { IQuery, IQueryFetchBoardsArgs } from "../../src/commons/types/generated/types";

const FETCH_BOARDS = gql`
  query fetchBoards($page: Int) {
    fetchBoards(page: $page) {
      _id
      writer
      title
      contents
    }
  }
`;
export default function StaticRoutedPage() {
  const { data, refetch } = useQuery<Pick<IQuery, "fetchBoards">, IQueryFetchBoardsArgs>(FETCH_BOARDS);

  const onClickPage = (event: MouseEvent<HTMLSpanElement>) => {
    void refetch({ page: Number(event.currentTarget.id) });
  };

  return (
    <>
      {/* 임시 배열 10개를 생성하여, 데이터가 없을 때도 높이 30px을 유지하여 reflow 방지 */}
      {(data?.fetchBoards ?? new Array(10).fill(1)).map(el => {
        return (
          <div key={el._id} style={{ height: "30px" }}>
            <span style={{ margin: "10px" }}>{el.writer}</span>
            <span style={{ margin: "10px" }}>{el.title}</span>
          </div>
        );
      })}
      {new Array(10).fill(1).map((_, index) => (
        <span key={index + 1} id={String(index + 1)} onClick={onClickPage}>
          {index + 1}
        </span>
      ))}
    </>
  );
}

위와 같이 데이터를 뿌려주는 곳 height를 고정시키면 위치상으로 다시 그려야 하는 일이 없기 때문에 reflow가 일어나는 것을 방지할 수 있습니다.

🎨 prefetch

  • html을 받아와서, 주소들을 모두 골라내서 일단 요청을 보내놓고, 그 다음 html 코드를 하나씩 실행한다.
  • 다음페이지에서 쓰려고 미리 받는 것이며, 현재페이지를 모두 받아온 이후 제일 나중에 다운로드 해오게 됩니다.
  • prefetch를 이용하면 페이지가 이동되어도 기다리지 않고 바로 보여주는 것이 가능합니다.
<!DOCTYPE html>
<html lang="ko">
  <head>
    <title>프리페치</title>

    <!-- 프리페치: 다음페이지를 미리 다운로드 받으므로, 버튼 클릭시 페이지이동 빠름 -->
    <link rel="prefetch" href="board.html" />
  </head>
  <body>
    <a href="board.html">게시판으로 이동하기</a>
  </body>
</html>

🎨 preLoad

  • 현재페이지에서 쓸 이미지들을 모두 다운로드 받아놓는 것입니다.
  • 따라서 이미지를 index.html에서 받아올 때, css와 js보다 먼저 받아오게 됩니다.
  • 이미지를 먼저 받아오기 때문에 화면로드 지연을 방지할 수 있습니다.
<!DOCTYPE html>
<html lang="ko">
  <head>
    <title>프리로드</title>

    <!-- 프리로드: 한 번에 6개씩 받아오므로, body태그의 이미지는 가장 마지막에 다운로드 -->
    <!--         눈에 보이는 이미지를 먼저 다운로드 받아서 보여주고, 클릭하면 실행되는 JS는 나중에 받아오기 -->
    <!--         따라서, DOMContentedLoaded 이후, Load까지 완료되는 최종 로드 시간이 더 짧아짐 -->
    <link rel="preload" as="image" href="./dog.jpeg" />

    <!-- 일반로드 -->
    <link rel="stylesheet" href="./index.css" />
    <script src="index1.js"></script>
    <script src="index2.js"></script>
    <script src="index3.js"></script>
    <script src="index4.js"></script>
    <script src="index5.js"></script>
    <script src="index6.js"></script>
  </head>
  <body>
    <img src="./dog.jpeg" />
  </body>
</html>
profile
프론트엔드 개발 공부

0개의 댓글