Optimize header component

김병민·2022년 10월 28일
0

TIL

목록 보기
68/68

Optimize header component

프로젝트 진행 중 적용해 본 최적화에 대해 기술해보려합니다.

re-render

우선 렌더링(rendering)이란 무엇인지부터 확인하고 가야할 것 같습니다.

렌더링이란 컴포넌트가 현재 상태값을 바탕으로 UI를 구성하는 것을 말합니다. 예를 들어

    <Link href={url}>
      <a className={isSelected ? `${className} Selected` : className}>{text}</a>
    </Link>

위 코드에서 컴포넌트는 상태 href=url, className="000" text=test로 화면상에 UI를 꾸미는 것입니다.

그렇다면 리액트에서 렌더링은 언제 일어날까요 ?

Props가 변경되었을 때
State가 변경되었을 때
useEffect
부모 컴포넌트가 렌더링되었을 때

위와 같은 상황에서 렌더링이 발생하는 것입니다.

리렌더링이 무조건적으로 나쁜 것은 아닙니다. 상태값이 바뀌어야 할 때 적정하게 리렌더링이 이루어져야만 컴포넌트는 변할 것입니다. 하지만 필요 이상의 리렌더링이 발생한다면 웹 애플리케이션의 성능은 저하될 것입니다.

그럼 어떻게 리렌더링을 잡았는 지 적어보도록 하겠습니다.

re-render header component

위 영상을 보면 링크(메뉴바 클릭)가 변할 때 마다 모든 메뉴바가 다시 렌더링되는 것을 확인하실 수 있습니다.

즉, 트렌드에서 공간 페이지로 이동 시 모든 메뉴들이 새롭게 구성되는 것입니다.

이는 불필요한 리렌더링입니다.

저는 링크 이동이 발생할 때마다 클릭 한 링크와 이전의 링크의 색상 변화(className 변화)만 바뀌기에 이 두 컴포넌트만 리렌더링이 이루어져야하고 나머지는 그대로여야합니다. 이를 위해 사용하는 것이 React.memo입니다.

React.memo
컴포넌트가 동일한 props로 동일한 결과를 렌더링해낸다면, React.memo를 호출하고 결과를 메모이징(Memoizing)하도록 래핑하여 경우에 따라 성능 향상을 누릴 수 있습니다. 즉, React는 컴포넌트를 렌더링하지 않고 마지막으로 렌더링된 결과를 재사용합니다

import Link from "next/link";
import React, { ReactNode } from "react";

interface ICustomLinkProps {
  url: string;
  isSelected: boolean;
  className?: string;
  text: ReactNode | string;
}

const CustomLink = ({ url, text, className, isSelected }: ICustomLinkProps) => {
  console.log("custom render", url, className);

  return (
    <Link href={url}>
      <a className={isSelected ? `${className} Selected` : className}>{text}</a>
    </Link>
  );
};

export default React.memo(CustomLink);

마지막 줄 React.memo()를 통해 props가 변경되지 않으면 기존의 컴포넌트를 렌더링합니다.

그럼 처음에만 모든 컴포넌트가 렌더링되고 이후에는 변해야할 컴포넌트만 렌더링이 되는 것을 확인하실 수 있습니다.

하지만 영상 마지막 부분에 이상한 점이 있습니다. 트렌드와 검색 버튼은 두번씩 렌더링이 되고 있습니다. 이는 모바일 컴포넌트를 따로 두고 있기 때문입니다.

Dynamic import

데스크탑 환경에서는 mobile 메뉴창이 렌더링되면 안됩니다. 이럴 땐 dynamic import를 사용하여 막습니다.

const DynamicMobileNavigation = dynamic(() => import("./MobileNavigation"));

const DynamicNavigation = dynamic(() => import("./Navigation"));

  const [isMobile, setIsMobile] = React.useState(false);

  const handlerResize = () => {
    setIsMobile(() => {
      return window.innerWidth <= sizes.mobile;
    });
  };

  React.useEffect(() => {
    handlerResize();
    window.addEventListener("resize", handlerResize);
    return () => {
      window.removeEventListener("resize", handlerResize);
    };
  }, []);

이런식으로 window size를 통해 해당컴포넌트를 특정 사이즈에만 가지고 오는 방법이다.

이렇게 화면이 작아질 때 컴포넌트를 서버에서 가지고 오는 것을 확인할 수 있다.

마지막

물론 이 방법들이 정답은 아닙니다. 극단적인 예를 위해서 사용하는 방법들일 뿐입니다. 각자의 웹 페이지 상황에 맞춰 적절한 곳에 최적화를 진행해보면될 듯합니다. 다음에는 폰트를 최적화를 프로젝트에 적용하도록 해보겠습니다.

profile
I'm beginner

0개의 댓글