쿠팡이츠 클론 - Infinite Scroll
프로젝트에 인피니트 스크롤링을 활용한 사례를 정리했습니다.
1. 인피니트 스크롤링을 하는 이유?
2. 프로젝트 구현
인피니트 스크롤링을 하는 이유?
인피니트 스크롤링이란 말 그대로 무한 스크롤이다. 페이지를 클릭하면 다음 페이지 주소로 이동하는 페이지네이션과 달리 페이지 하단에 도달하면 새로운 콘텐츠가 한 화면에 추가로 로드되는 식이다. facebook, instagram이 이러한 방식으로 콘텐츠를 로드하고 있다. 데이터 전부를 화면에 보이지 않는 부분까지 표시해주면 오래 걸릴 수 있기 때문에 인피니트 스크롤링을 해준다.

일정 높이가 됐는지 감지하기.
페이지가 일정 부분까지 내려갔을 때 요청을 보내주려면 유저가 어느 정도의 위치인지 체크해줘야 한다.
세로 스크롤만 감지하면 되니 height와 관련된 값을 보자.
- scrollY: 유저가 얼마나 내렸는지
- scrollHeight: 화면에 보이지 않는 높이도 포함된 페이지의 총 높이
- clientHeight: 유저에게 보이는 페이지의 높이
그러면 scrollY(유저가 내린 위치) + scrollHeight(유저에게 보이는 페이지의 높이) === clientHeight(페이지에 총 높이)의 뜻은 스크롤을 다 내렸다는 뜻이다.
프로젝트 구현


우선 getServerSideProps로 페이지가 로드되기 전 화면에 표시해줄 store 데이터를 서버로부터 전부 가져온다.
화면에는 가져온 store 데이터를 slice 함수로 0부터 storeid 개수만큼 끊어 map함수를 이용해 렌더링 해준다.
여기서 storeid는 기본값이 10인 redux store에 저장되어 있는 값이다.

useEffect 훅으로 store storeid loadStoresLoading이 바뀔 때마다 onScroll 함수가 실행되게 해 준다.
유저가 총높이보다 150px 만큼 내린 시점부터 scroll event를 준다.
useEffect에서 return으로 removeEventListener를 해준 이유는 해주지 않으면 메모리 과부하가 일어나기 때문이다.




또 150px부터 스크롤 이벤트가 너무 많이 실행되기 때문에 saga에선 throttle 이팩트를 통해 1초마다 요청을 할 수 있게 조절하였고 또한 리듀서에서 SUCCESS 처리가 되지 않으면 loadStoresLoading이란 상태 값은 true로 지정해
로딩 중이 아닐 때만 요청을 보낼 수 있게 조절하였다.
마지막으로 한 번에 모든 store data를 가져왔다고 하였는데 원래는 서버에서 data를 10개씩 끊어서 받으려고 하였다.
그러나 프로젝트 특성상 data는 서버에서 랜덤 순서로 전해오기 때문에 10개씩 끊어 받는 경우 중복의 문제가 발생하였다. 그래서 처음에 모든 data를 받은 이후 스크롤이 이벤트 발생 시 MORE_STORES 액션을 디스패치 해주어
storeid 상태를 +10 씩 해줘 화면에 10개씩 추가되게 설정하였다.
최종적으로는 MORE_STORES 액션을 디스 패치해서 store data가 추가되는 경우는
유저가 총높이보다 150px 만큼 내린 시점 && storeid가 store data의 총길이보다 작을 때 && Loading 중이 아닐 때만 이다.