초기 로딩속도 개선하기

oweaj·2023년 11월 23일
0

React는 초기 로딩시 모든 스크립트 파일을 로드 하는 CSR(Client Side Rendering)로 필요한 파일만 로드하는 SSR(Server Side Rendering)에 비해 느리다. 이러한 이유로 전에 공모전에 제출했던 프로젝트 성능점수를 Lighthouse로 체크한 결과 성능점수가 다소 낮은편으로 성능최적화를 위해 초기 로딩 속도를 개선시켜 보려고한다.

[ Lighthouse의 성능 수치에 대한 설명과 가중치 값 ]

Lighthouse 성능 점수 참고 문서

FCP(First Contentful Paint) : 최초 콘텐츠가 포함된 페인트. 초기 DOM 콘텐츠를 렌더링하는데 걸리는 시간을 측정 - 10%
SI(Speed Index) : 속도 지수. 콘텐츠가 시각적으로 표시되는 진행 속도를 측정 (ex. 리로드되는 페이지의 비디오를 캡쳐하여 프레임 간의 속도를 계산) - 10%
LCP(Largest Contentful Paint) : 가장 큰 콘텐츠가 포함된 페인트. 가장 큰 콘텐츠를 렌더링 하는데 걸리는 시간 - 25%
TBT(Total Blocking Time) : 총 차단 시간. 마우스 클릭, 화면 탭 또는 키보드 누름과 같은 사용자 입력에 페이지가 응답하지 못하도록 차단된 총 시간 - 30%
CLS(Cumulative Layout Shift) : 누적 레이아웃 이동. 사용자가 예상치 못한 레이아웃 이동을 경험하는 것에 대한 점수 - 25%

1. 개선 전 프로젝트 성능

개선 전 프로젝트를 보면 bundle.js 파일 용량이 3.1mb, 로딩에 소요된 시간은 0.4초 정도이고, Lighthouse의 분석을 보면 LCP 3.4초, SI 2.2초로 총 성능 66점으로 개선 하기 전 프로젝트의 성능을 볼 수 있다.

2. 로딩 속도 개선 하기

개선 하기전에 먼저 React.lazy와 Suspense에 대해 알아보면 React.lazy는 동적으로 컴포넌트를 로딩하는 기능으로 사용자가 실제로 사용할 때만 로드할 수 있게 해주고, 초기 로딩 시간을 줄여준다. 또한 Suspense는 React.lazy를 통해 로딩된 컴포넌트를 래핑 할 수 있으며 컴포넌트가 로드되는 동안의 상태를 처리하는 역할이다.
그러므로 전체 코드를 하나의 큰 번들 대신 여러 개의 작은 번들로 나누는 코드 스플리팅으로 사용자가 필요할 때만 로드할 수 있기 때문에 초기 로딩 속도가 향샹되는 점에서 사용하는 이유이다.

// 기존 App.tsx
import Landing from './pages/Landing/Landing';
import Main from './pages/Main/Main';
import SignIn from './pages/SignIn/SignIn';
import SignUp from './pages/SignUp/SignUp';
import ChattingList from './pages/Chatting/ChattingList';
import Chatting from './pages/Chatting/Chatting';
import Map from './pages/Map/Map';
import MyPage from './pages/MyPage/MyPage';
import NotFound from './pages/NotFound/NotFound';
import SelectLocation from './pages/Main/SelectLocation';
import HostList from './pages/Main/HostList';
import MyWrite from './pages/MyPage/MyWrite';
import Favorite from './pages/MyPage/Favorite';
import Notice from './pages/MyPage/Notice';
import Board from './pages/Board/Board';
import WriteBoard from './pages/Board/WriteBoard';
import Host from './pages/MyPage/Host';
import Navigation from './components/Navigation/Navigation';
import ProfileEdit from 'components/MypageInfo/ProfileEdit';

기존에 이렇게 페이지들을 import한 App파일이다. 이렇게 해도 프로젝트를 진행하는 점에 문제는 없지만 사용자 입장에서 보면 첫 페이지에 들어가게되면 모든 페이지를 로드하기 때문에 로딩속도가 느려지는 문제가 생겨 사용자에게 불편함을 줄 수 있다.

// lazy 적용 App.tsx
const Landing = lazy(() => import('./pages/Landing/Landing'));
const Main = lazy(() => import('./pages/Main/Main'));
const SignIn = lazy(() => import('./pages/SignIn/SignIn'));
const SignUp = lazy(() => import('./pages/SignUp/SignUp'));
const ChattingList = lazy(() => import('./pages/Chatting/ChattingList'));
const Chatting = lazy(() => import('./pages/Chatting/Chatting'));
const Map = lazy(() => import('./pages/Map/Map'));
const SelectLocation = lazy(() => import('./pages/Main/SelectLocation'));
const MyPage = lazy(() => import('./pages/MyPage/MyPage'));
const Host = lazy(() => import('./pages/MyPage/Host'));
const HostList = lazy(() => import('./pages/Main/HostList'));
const MyWrite = lazy(() => import('./pages/MyPage/MyWrite'));
const Favorite = lazy(() => import('./pages/MyPage/Favorite'));
const Notice = lazy(() => import('./pages/MyPage/Notice'));
const Board = lazy(() => import('./pages/Board/Board'));
const WriteBoard = lazy(() => import('./pages/Board/WriteBoard'));
const Navigation = lazy(() => import('./components/Navigation/Navigation'));
const ProfileEdit = lazy(() => import('components/MypageInfo/ProfileEdit'));
const NotFound = lazy(() => import('./pages/NotFound/NotFound'));


<Suspense fallback={<div>Loding...</div>}>
  <Routes>
    <Route path="/" element={<Landing />} />
    <Route path="/signin" element={<Redirect token={token} element={<SignIn />} />} />
    <Route path="/signup" element={<Redirect token={token} element={<SignUp />} />} />
    <Route element={<Navigation />}>
      <Route path="/main" element={<Main />} />
      <Route path="/main/selectLocation" element={<SelectLocation />} />
      <Route path="/main/hostlist/:regionCode/:regionName" element={<HostList />} />
      <Route path="/map" element={<Map />} />
      <Route path="/board" element={<Board />} />
      <Route path="/board/writeboard" element={<WriteBoard />} />
      <Route path="/mypage" element={<MyPage />} />
      <Route path="/mypage/profileEdit" element={<ProfileEdit />} />
      <Route path="/mypage/mywrite" element={<MyWrite />} />
      <Route path="/mypage/favorite" element={<Favorite />} />
      <Route path="/mypage/notice" element={<Notice />} />
      <Route path="/mypage/host" element={<Host />} />
      <Route path="/mypage/host/edit" element={<Host />} />
      <Route path="/chatting/:roomnum" element={<Chatting />} />
      <Route path="/chattinglist" element={<ChattingList />} />
      <Route path="/oauth2/redirect/:token" element={<KakaoRedirect />} />
      <Route path="/oauth2/redirect/:token" element={<GoogleRedirect />} />
    </Route>
    <Route path="*" element={<NotFound />} />
  </Routes>
</Suspense>

이렇게 React.lazy와 Suspense를 적용하면 전부 로드되지않고 필요한 컴포넌트만 로드 되기 때문에 로딩 시간을 단축시킬수있다.

3. 개선 후 프로젝트 성능

개선 후 bundle.js 파일 용량이 3.1mb -> 501kb로 줄었으며 로딩에 소요된 시간은 0.4초 -> 0.078초로 빨라졌다.
또한 Lighthouse의 측정항목을 보면 SI 2.2초 -> 0.9초, LCP 3.4초 -> 2.0초, TBT 0.28초 -> 0.01초로 개선 되었으며 66점에서 91점으로 전체 성능 점수가 상향된 부분을 알 수 있었다.

profile
데굴데굴데굴데굴데굴

0개의 댓글

관련 채용 정보