성능 개선의 필요성 인식
진행하고 있는 프로젝트의 상세페이지는 SSR로 구현 되어있다.
프로젝트 MVP 주간에는 페이지가 렌더링 되면 클라이언트 사이드에서 데이터를 요청하는 방식이였으나
SSR의 장점을 활용하지 못한다고 판단하였고 react query의 prefetching 을 활용하는 방향으로 성능 개선을 진행하였다.
react-query 의 prefetching 활용
우리 서비스를 이용하는 사용자는 대부분 상세페이지를 클릭할 것이다.
이럴 경우 사용자가 상세페이지에 필요한 데이터를 기다릴 필요가 없도록 미리 데이터를 가져오면 보다 좋은 사용자 경험을 제공할 것이다.
이때 사용 할 수 있는것이 react query의 prefetching 이다.
상세페이지는 prefetching 을 사용함에 있어 적합한가?
1) 상세페이지에 들어가는 모집공고문의 데이터는 비교적 안정적이기 때문에 prefetching 에 특히 적합하다고 판단한다.
2) 모집공고문의 데이터는 실시간으로 변동하는 주식시세와 같은 동적인 데이터를 가져오는 것이 아니기 때문에 캐시 된 데이터에 의존하더라도 문제가 되지 않을 가능성이 매우 높다고 생각했다.
3) 유입되는 사용자의 대부분은 메인페이지에서 페이지가 로드 될 것이다.
그렇기 때문에 상세페이지에 필요한 데이터가 캐시에 미리 로드 되고,
로드된 데이터의 캐시 시간이 다 되기전에 사용자가 상세페이지로 이동하는 한 사용자는 서버호출을 할때까지 기다릴 필요가 없다.
사용자가 기다릴 필요가 없다는 것은 그만큼 더 좋은 사용자 경험을 제공하는 것이다.
NextJs에서 prefetching 사용 하기 위해선
공식문서에 따른 두 가지 방법이 있다.
- initialData
- 서버에서 캐시를 dehydrate 후 클라이언트에서 hydrate를 하는 방식
첫 번째 방법의 사용법은 간단하지만, 클라이언트 사이드에서 해당 데이터를 사용하는 컴포넌트까지 props로 넘겨주어야 하는 비효율적인 작업이 동반된다.
두 번째 방법은 위와 같은 비효율적인 작업은 없지만 프론트에서 셋업 해야 할 것 들이 있다.
우리는 두 번째 방법을 채택하였다.
서버에서 캐시를 dehydrate 후 클라이언트에서 hydrate를 하는 방식
1. 공식문서에서 알려주는 대로 최상단 컴포넌트에서 보일러 플레이트 코드를 작성하였다.
_app.tsx에서 pageProps에 전달된 dehydrate된 props를 가져와서 hydrate시킨다. 즉, getServerSideProps에서는 데이터를 가진 상태의 dehydrate state를 전달하고, 다시 클라이언트에서 hydrate한다.
이렇게 세팅을 마치면 useQuery에서 동일한 queryKey로 값에 접근할 수 있다.
2.getServerSideProps에서 새로운 QueryClient를 생성하고 해당 QueryClient에 값을 prefetch한다. 그리고 이 queryClient를 dehydrate시켜서 props로 전달한다.
처음 1회는 SSR로 값을 받아와서 캐시에 데이터가 저장 되고, stale 상태가 된 이후에는 클라이언트에서 동일하게 API호출을 하여 값을 갱신하게 된다.
결과
prefetch 이후 LightHouse 로 상세페이지에 대한 성능을 측정한 결과 TTI를 4초에서 0.2초로 단축시킬수 있는 엄청난 성능을 보여주었다.
'개발 일지 > React' 카테고리의 다른 글
useRef (0) | 2023.04.04 |
---|---|
[Next.js] styled-component 적용하기 (0) | 2023.03.16 |
[Next.js] A title element received an array with more than 1 element as children. In browsers title Elements can only have Text Nodes as children. 경고 (0) | 2023.02.27 |
새로고침시 데이터에 undefined가 들어온다면 (0) | 2023.02.23 |
Next.js 에선 <img> 보다는 <Image> (0) | 2023.02.11 |