본문 바로가기
React & TypeScript

React 프로젝트 성능 및 최적화 개선하기

by 어느새벽 2024. 12. 12.

사이드 프로젝트를 어느 정도 마무리하고 성능을 확인해봤는데 ....... 

왜이리 점수가 짜나요....

랜딩페이지와 디자인에 힘을 많이 주는 프로젝트라 이미지 최적화가 시급했다.

최적화 방법을 찾아보던 중 코드 스플리팅을 주로 사용한다는 것을 알았다.

아래는 개선 전 코드 .. 

import { createBrowserRouter } from "react-router-dom";
import App from "../App";
import Home from "../pages/home";
import Login from "../pages/auth/components/Login";
import Signup from "../pages/auth/components/Signup";
import Recipes from "../pages/recipes";
import MyPage from "../pages/mypage/MyPage";
import KakaoCallback from "../pages/auth/KakaoCallback";
import Votechat from "../pages/vote-chat";
import Community from "../pages/community";
import PrivatePage from "./PrivatePage";
import Test from "../pages/test";
import RecipeDetail from "../pages/recipes/detail/[id]";
import Detail from "../pages/community/detail/[id]/Detail";
import Upload from "../pages/community/upload/Upload";

const router = createBrowserRouter([
  {
    element: <App />,
    children: [
      {
        path: "/",
        element: <Home />
      },
      {
        path: "/login",
        element: <Login />
      },
      {
        path: "/signup",
        element: <Signup />
      },
      {
        path: "/recipe",
        element: <Recipes />
      },
      {
        path: "/kakao/callback",
        element: <KakaoCallback />
      },
      {
        path: "/vote-chat",
        element: <Votechat />
      },
      {
        path: "/community",
        element: <Community />
      },
      {
        path: "/community/:page",
        element: <Community />
      },
      {
        element: <PrivatePage />,
        children: [{ path: "/mypage", element: <MyPage /> }]
      },
      {
        path: "/test",
        element: <Test />
      },
      {
        path: "community/detail/:id",
        element: <Detail />
      },

      {
        path: "/community/detail/:id/:page",
        element: <Detail />
      },
      {
        path: "/recipe-detail/:id",
        element: <RecipeDetail />
      },
      {
        path: "/community/upload",
        element: <Upload />
      }
    ]
  }
]);

export default router;

 

개선 후 코드 ..! 

import { createBrowserRouter } from "react-router-dom";
import { lazy, Suspense } from "react";
import App from "../App";
import PrivatePage from "./PrivatePage";

// 로딩 UI 컴포넌트
const Loading = () => <div className="flex items-center justify-center h-screen">로딩 중...</div>;

// 페이지 컴포넌트를 동적으로 import
const Home = lazy(() => import("../pages/home"));
const Login = lazy(() => import("../pages/auth/components/Login"));
const Signup = lazy(() => import("../pages/auth/components/Signup"));
const Recipes = lazy(() => import("../pages/recipes"));
const KakaoCallback = lazy(() => import("../pages/auth/KakaoCallback"));
const Votechat = lazy(() => import("../pages/vote-chat"));
const Community = lazy(() => import("../pages/community"));
const MyPage = lazy(() => import("../pages/mypage/MyPage"));
const Test = lazy(() => import("../pages/test"));
const RecipeDetail = lazy(() => import("../pages/recipes/detail/[id]"));
const Detail = lazy(() => import("../pages/community/detail/[id]/Detail"));
const Upload = lazy(() => import("../pages/community/upload/Upload"));

const router = createBrowserRouter([
  {
    element: <App />,
    children: [
      {
        path: "/",
        element: (
          <Suspense fallback={<Loading />}>
            <Home />
          </Suspense>
        ),
      },
      {
        path: "/login",
        element: (
          <Suspense fallback={<Loading />}>
            <Login />
          </Suspense>
        ),
      },
      {
        path: "/signup",
        element: (
          <Suspense fallback={<Loading />}>
            <Signup />
          </Suspense>
        ),
      },
      {
        path: "/recipe",
        element: (
          <Suspense fallback={<Loading />}>
            <Recipes />
          </Suspense>
        ),
      },
      {
        path: "/kakao/callback",
        element: (
          <Suspense fallback={<Loading />}>
            <KakaoCallback />
          </Suspense>
        ),
      },
      {
        path: "/vote-chat",
        element: (
          <Suspense fallback={<Loading />}>
            <Votechat />
          </Suspense>
        ),
      },
      {
        path: "/community",
        element: (
          <Suspense fallback={<Loading />}>
            <Community />
          </Suspense>
        ),
      },
      {
        path: "/community/:page",
        element: (
          <Suspense fallback={<Loading />}>
            <Community />
          </Suspense>
        ),
      },
      {
        element: <PrivatePage />,
        children: [
          {
            path: "/mypage",
            element: (
              <Suspense fallback={<Loading />}>
                <MyPage />
              </Suspense>
            ),
          },
        ],
      },
      {
        path: "/test",
        element: (
          <Suspense fallback={<Loading />}>
            <Test />
          </Suspense>
        ),
      },
      {
        path: "/community/detail/:id",
        element: (
          <Suspense fallback={<Loading />}>
            <Detail />
          </Suspense>
        ),
      },
      {
        path: "/community/detail/:id/:page",
        element: (
          <Suspense fallback={<Loading />}>
            <Detail />
          </Suspense>
        ),
      },
      {
        path: "/recipe-detail/:id",
        element: (
          <Suspense fallback={<Loading />}>
            <RecipeDetail />
          </Suspense>
        ),
      },
      {
        path: "/community/upload",
        element: (
          <Suspense fallback={<Loading />}>
            <Upload />
          </Suspense>
        ),
      },
    ],
  },
]);

export default router;

 

개선 전 성능

 

개선 후 성능

 

권장사항 부분이 특히 많이 오른 것을 확인했다.

 

아직도 성능이 많이 낮은 이유를 보니

로딩 컴포넌트가 gif 파일이었는데 gif가 특히 용량을 많이 차지한다는 것을 알았다.

구글링을 통해 gif를 webm 파일로 변환하면 용량이 많이 줄어든다는 것을 알게되었다.

ffmpeg을 설치하여 파일 변환 명령어를 통해 형식을 바꾸면 된다(자세한 소개는 다음에 수정하겠다!)

처음에 mp4 파일로 변환했다가 배경이 있으면 안되는데 흰색 배경이 있는 채로 변환돼서 못 쓰게 되었다.

webm 파일을 쓰면 배경을 제거하여 변환해줘서 webm 변환을 선택하게 되었다.

(webm파일로 만든 후에도 style 적용을 따로 해줘서 프로젝트에 맞춰 사용할 수 있었다. + 추후 추가예정)

++추가

ffmpeg는 ios에서 지원을 안 한다고 한다 ...... 

mp4파일로 다시 변환해서 쓰려 했으나 화질도 너무 안 좋고 해서 

이미지 하나로 css 애니메이션 효과를 넣기로 했다.

 

삽질했지만 새로운 걸 알았으니 완죤 럭키비키쟈나 ><? 

 

이후 애플리케이션에 저장해둔 정적 이미지 png 파일들을 모두 webp 파일로 교체해줬다.

 

그 결과 

 

 

성능을 이만큼 높일 수 있었다.

다 초록색 링으로 만들고 싶은데 .... 또 열심히 구글링 해봐야겠다.