괜찮을지도 사이트 최적화 진행

@괜찮을지도 · October 18, 2023 · 3 min read

이 글은 우테코 괜찮을지도팀의 패트릭이 작성했습니다.

홈페이지에서 용량을 많이 차지하고 페이지 로딩 속도에 영향을 미치는 이미지와 번들 사이즈 최적화를 진행하였습니다.

이미지 최적화

홈페이지에서 가장 많은 용량을 차지하고 페이지 로딩 속도에 가장 큰 영향을 미치는 것은 이미지라는 의견이 나왔습니다. 백엔드 쪽에서는 이미지 업로드 용량 한계치를 두고 프론트 단에서 용량을 줄이기로 하였습니다.

browser-image-compression 라이브러리 사용

Alt text
Alt text

그리고 하나의 이미지와 여러 개의 이미지를 압축하는 곳이 따로 있어 구분해서 적용하기 위해 custom hook으로 분리하였습니다.

import imageCompression from 'browser-image-compression';

const useCompressImage = () => {
  const compressImage = async (file: File) => {
    const resizingBlob = await imageCompression(file, {
      maxSizeMB: 1, // 최대 이미지 용량
      maxWidthOrHeight: 750, // 최대 이미지 크기
      useWebWorker: true, // 비동기 처리 유무
    });
    const resizingFile = new File([resizingBlob], file.name, {
      type: file.type,
    });
    return resizingFile;
  };

  const compressImageList = async (files: FileList) => {
    const compressedImageList: File[] = [];

    for (const file of files) {
      const compressedImage = await compressImage(file);
      compressedImageList.push(compressedImage);
    }

    return compressedImageList;
  };

  return { compressImage, compressImageList };
};

export default useCompressImage;

이를 통해 성능이 개선된 지표입니다.

Alt text
Alt text

번들 사이즈

이미지 다음으로 번들 사이즈가 페이지 로딩 속도에 영향을 끼친다는 것을 알았습니다. 동적 import(lazy, suspense 이용)와 tree shaking을 통해 개선할 수 있었습니다.

const SelectedTopic = lazy(() => import('./pages/SelectedTopic'));
const NewPin = lazy(() => import('./pages/NewPin'));
const NewTopic = lazy(() => import('./pages/NewTopic'));
const SeeAllPopularTopics = lazy(() => import('./pages/SeeAllPopularTopics'));
const SeeAllNearTopics = lazy(() => import('./pages/SeeAllNearTopics'));
const SeeAllLatestTopics = lazy(() => import('./pages/SeeAllLatestTopics'));
const KakaoRedirect = lazy(() => import('./pages/KakaoRedirect'));
const Profile = lazy(() => import('./pages/Profile'));
const AskLogin = lazy(() => import('./pages/AskLogin'));
const Bookmark = lazy(() => import('./pages/Bookmark'));
function SuspenseComp({ children }: SuspenseCompProps) {
  return <Suspense fallback={null}>{children}</Suspense>;
}

{
  path: 'topics/:topicId',
  element: (
    <SuspenseComp>
      <SelectedTopic />
    </SuspenseComp>
  ),
  withAuth: false,
},
{
  path: 'new-topic',
  element: (
    <SuspenseComp>
      <NewTopic />
    </SuspenseComp>
  ),
  withAuth: true,
},
{
  path: 'new-pin',
  element: (
    <SuspenseComp>
      <NewPin />
    </SuspenseComp>
  ),
  withAuth: true,
},
{
  path: 'see-all/popularity',
  element: (
    <SuspenseComp>
      <SeeAllPopularTopics />
    </SuspenseComp>
  ),
  withAuth: false,
},
{
  path: 'see-all/near',
  element: (
    <SuspenseComp>
      <SeeAllNearTopics />
    </SuspenseComp>
  ),
  withAuth: false,
},
{
  path: 'see-all/latest',
  element: (
    <SuspenseComp>
      <SeeAllLatestTopics />
    </SuspenseComp>
  ),
  withAuth: false,
},
{
  path: 'favorite',
  element: (
    <SuspenseComp>
      <Bookmark />
    </SuspenseComp>
  ),
  withAuth: true,
},
{
  path: 'my-page',
  element: (
    <SuspenseComp>
      <Profile />
    </SuspenseComp>
  ),
  withAuth: true,
},
{
  path: '/askLogin',
  element: (
    <SuspenseComp>
      <AskLogin />
    </SuspenseComp>
  ),
  withAuth: false,
},
  • 개선 전
    Alt text
    Alt text
  • 개선 후
    Alt text
    Alt text
@괜찮을지도
안녕하세요! 괜찮을지도 기술블로그입니다.