CSR 환경에서 Suspense로 발생한 문제 해결하고 성능 개선하기 | 카카오페이 기술 블로그
tech.kakaopay.com
loader를 사용하여 API 병렬적으로 호출하기
https://tech.kakaopay.com/post/react-router-dom-csr-prefetch/#react-router-dom-%EA%B8%B0%EB%B0%98%EC%9D%98-csr-%EB%9D%BC%EC%9A%B0%ED%8C%85
선언형 컴포넌트에 대한 정리와 코드 예시를 볼 수 있는 글
https://tech.kakaopay.com/post/react-query-2/
위의 글에서 다루는 개념에 대해 정리한 글
https://hengxi.tistory.com/20
요약
UI 개발 패턴 - Concurrent UI Pattern : 선언적 UI 패턴
선언형 컴포넌트 - 무엇을(What) 보여줄 것인가.
명령형 컴포넌트 - 어떻게(How) 보여줄 것인가.
suspense의 fallback을 통해 적재적소의 UI를 보여줄 수 있다.
즉, 선언적으로 어떤 컴포넌트를 보여줄지 알 수 있는 것이고, 비동기적 로직이 있을 때, 해당 로직이 완료된 이후에 렌더링을 하기 때문에 꼼꼼하게 추가만 한다면 오히려 최적화가 잘 된다.
선언적으로 UI를 구성할 경우 컴포넌트들의 관심을 확실하게 분리할 수 있고, 유지보수가 편리한 프로젝트 환경을 유지할 수 있으며 사용자 경험 향상을 위한 다양한 UI 요소를 활용할 수 있다.
react-query와 suspense를 같이 사용했을 때
문제 | 순차적인 API 호출로 네트워크에서 비용 소모가 크다.
제시 | API 호출을 병렬적으로 할 수 있는 방법
1. useQueries 사용 -> 기존 코드의 구조를 벗어남 + suspense를 사용한 확장성이 어려움
2. loader 사용
해결 | loader를 사용하는 방법
-> 쿼리의 타입에 따라 prefetchQuery 또는 prefetchInfiniteQuery 사용하여 데이터를 prefetch 할 수 있다.
세부 문제: suspense의 fallback 요소 렌더링이 안됨
세부 해결:
- react-router-dom의 defer를 사용하여 loader의 반환값이 지연된 값임을 명시
- Await 컴포넌트를 사용하여 useLoaderData 반환값인 Promise가 resolve 될 경우 fallback 요소를 언마운트하고 하위 요소를 렌더링
결과 | 로딩 시간이 평균 1.3초 -> 0.9초로 약 30% 성능 개선
loader 사용 시 주의할 점
1. API 변경 시 loader에서도 동일하게 변경해야 한다.
2. 페이지에서 호출하는 API 중 어떤 것을 prefetch할지 고민해야 한다.
3. HTTP 1.1에서는 병렬로 요청하여도 한 번에 유지되는 커넥션 개수의 제한이 있다. - 크롬의 경우 6개
결론
그동안 명령형 컴포넌트를 통해 사용하였는데, react-query와 react-router-dom을 같이 사용한다면 충분히 suspense를 통해 해결할 수 있다는 점, 두 개를 같이 사용하는 게 좋은 이유, 해결책을 찾아서 적용하고 결과를 수치화하여 나타내는 점을 배울 수 있었습니다.
다음 내용이 궁금하다면?
이미 회원이신가요?
2023년 11월 28일 오전 1:04