문제 상황
프로젝트에서 포켓몬 리스트를 무한 스크롤로 구현하고, 세대별로 필터링하는 기능을 추가했습니다. 그러나 세대별 데이터를 필터링할 때마다 무한 스크롤 데이터로 초기 데이터만 20개가 있고 필터링된 데이터는 새로 요청을 해서 필터링될 때마다 UI 깜빡임이 발생하는 문제가 있었습니다. 이 깜빡임은 API 요청 중 로딩되는 상태에서 생기는 문제로 리액트의 장점인 SPA을 통한 강력한 사용자 경험(UX)과 거리가 멀어보였습니다.
해결 방법: Skeleton 로딩 사용
깜빡임 문제를 해결하기 위해 Skeleton 로딩을 사용했습니다. Skeleton 로딩은 로딩 중에 리스트와 동일한 UI를 유지해 줬습니다.
const PokemonSkeletonList = ({ count = 12 }) => (
<>
{Array(count)
.fill(0)
.map((_, index) => (
<li
key={index}
className="border shadow-md p-4 m-4 rounded-3xl w-48 bg-white"
>
/* 리스트와 동일한 스타일링 */
</li>
))}
</>
);
시도한 방법: Tanstack Query와 리액트 훅 활용
Tanstack Query의 장점인 캐싱을 통한 효율적인 데이터 통신과 useState와 useEffect 그리고 useMemo를 통해 데이터를 저장해 놨다가 필터링된 데이터를 불러와주면 빠르면서 부드럽게 렌더링 될 것이라고 예상했습니다. 하지만 데이터를 처음에 1세대만 20개 저장하고 나머지 세대는 미리 fetch를 해줬어야 했는 데 사용하지 않을 데이터를 API을 요청하는 것은 이상해 보여서 다른 방법을 수색하기로 결정했고 스켈레톤 로딩으로 해결하기로 결정 했습니다.
생각한 방법: Next.js (SSR + CSR) 활용하기
지금 하는 프로젝트가 리액트 프로젝트였지만 만약 Next.js의 14버전이였다면 컴포넌트 단위로 SSR, CSR 이 나뉘어져서 한 페이지 안에 토글을 하는 컴포넌트와 리스트 컴포넌트를 잘 활용하면 깜빡이지 않고 렌더링 후 보여주지 않을까? 생각했지만 근본적으로 클라이언트 사이드에서 데이터를 필터링하거나 새로운 데이터를 fetch하는 경우, 결국 클라이언트 측에서 동적으로 데이터를 요청해야하는 것은 똑같아서 해결하는 방법은 데이터를 미리 받아오는 프리페칭 기법을 사용하거나 스켈레톤 로딩을 사용하는 방법이라고 생각했습니다.
프리패칭의 장단점
장점
- 사용자 경험 개선: 사용자가 특정 데이터를 요청하기 전에 데이터를 미리 가져와서 로딩 시간을 줄일 수 있습니다. 이는 사용자 경험을 크게 개선할 수 있습니다.
- 반응성 향상: 페이지나 컴포넌트가 즉각적으로 반응하도록 할 수 있습니다. 사용자가 특정 액션을 취했을 때 이미 데이터가 로드되어 있다면, 즉시 UI를 업데이트할 수 있습니다.
- 네트워크 효율성: 네트워크 상태가 좋을 때 데이터를 미리 받아두면, 실제 사용 시점에는 네트워크 요청을 줄일 수 있습니다.
단점
- 불필요한 데이터 요청: 사용자가 실제로 필요하지 않을 데이터를 미리 가져오는 것은 리소스 낭비일 수 있습니다. 이는 서버 부하와 네트워크 트래픽을 증가시킬 수 있습니다.
- 복잡성 증가: 프리패칭 로직을 구현하는 것은 추가적인 복잡성을 유발할 수 있으며, 캐싱 및 상태 관리 측면에서 어려움을 초래할 수 있습니다.
- 사용자 행동 예측의 어려움: 사용자가 어떤 데이터를 필요로 할지 정확히 예측하기 어렵기 때문에, 잘못된 데이터를 미리 가져오게 될 위험이 있습니다.
결론
포켓몬 리스트를 무한 스크롤로 구현하면서 발생한 UI 깜빡임 문제를 해결하는 방법을 알아봤습니다. Skeleton 로딩을 사용하여 로딩 중에도 동일한 UI를 유지해서 사용자 경험을 개선할 수 있음을 배웠습니다. 이를 통해 깜빡임 문제를 해결하고, 불필요한 데이터 요청을 줄이는 방법을 고민하게 되었습니다.
'TIL' 카테고리의 다른 글
TIL - 소셜 로그인 기능 추가 도중 트러블 슈팅 (0) | 2024.07.06 |
---|---|
TIL - 리액트 훅과 가상 DOM의 상호작용 (0) | 2024.07.05 |
TIL - 재사용 가능한 컴포넌트 만들기: class-variance-authority 활용 (0) | 2024.07.03 |
TIL - 북마크된 영화 목록 기능 구현을 위한 고민과 해결 방안 (0) | 2024.07.02 |
TIL - Next.js&supabase에서 createClient Vs. createServerComponentClient (0) | 2024.07.01 |