프리온보딩 코스 첫번째 과제로 infinite scroll 구현하기 당첨..!
페이지네이션은 해봤어도 이건 처음인데 .. 흐흐흑
하지만 난 혼자가 아니야 우리 7ill resource 민기님과 함께라면 할 수 있다 이말이야!!
무한스크롤?
무한 스크롤은 사용자가 페이지 하단에 도달했을 때, 콘텐츠가 계속 로드되는 사용자 경험(UX, User EXperience) 방식이며, 이는 마치 끝이 없는 단일 페이지에서 끝없는 정보의 흐름을 경험하게 만든다.
무한스크롤 프로세스
1. 스크롤이 페이지 최하단에 위치했는지를 확인
2. 최하단이라면 예정된 이벤트를 실시
3. 콘텐츠가 비동기식으로 하단에 추가됨
4. 비동기 요청이 끝났다면 계속 스크롤을 감시
스크롤이 페이지 최하단에 위치했는지 어떻게 확인할까?
1. scroll 윈도우 객체 또는 특정 element에 eventListenr를 추가
이 방법은 scroll 이벤트 이벤트가 수백번 호출되고, 메인 스레드에 영향을 준다. 감지하는 이벤트가 끊임없이 호출되기 때문에 성능에 영향을 주는 것이다.
2. Intersection Observer
target 요소와 상위 요소 또는 최상위 document의 viewport 사이의 intersection(교차 지점)을 감지한다.
Intersection Observer API를 이용해 target 요소가 교차지점에 들어오거나 나갈 때 감지하여 미리 등록된 콜백 함수를 실행시키기 때문에 메인 스레드의 점유가 줄어든다.
Intersection Observer로 무한스크롤 구현하기!
Intersection Observer 생성
const observer = new IntersectionObserver(callback, options);
callback
target 요소가 교차지점에서 들어오거나 나갈 때마다 감지하여 callback 함수가 실행된다.
options
const option = {
root: null,
rootMargin: "200px",
threshold: 0.2,
};
- root: 교차 지점을 감시하는 영역을 설정할 수 있다. root를 지정할 경우 반드시 target의 상위 요소여야 한다. 설정하지 않거나 null로 설정하면 브라우저 뷰포트를 기본값으로 사용한다.
- rootMargin: root가 가진 margin을 말하며, CSS margin 속성처럼 "10px", "10px 20px" 등 형태가 가능하며 음수값사용도 가능하다. 이 값에 의해 root 요소의 여백을 늘리거나 줄일 수 있다. 기본값은 0px
- threshold: target 요소가 root간의 교차 퍼센트를 나타내는 단일 숫자 or 숫자배열이다. 콜백함수 호출 시점을 결정하는 옵션이며, 기본값은 0
Infinite Scroll 만들기
useEffect(() => {
if (target.current) {
const observer = new IntersectionObserver(onIntersect, option);
observer.observe(target.current);
return () => observer && observer.disconnect();
}
}, [onIntersect, target]);
IntersectionObserver를 등록하고 ref를 컴포넌트 최하단 element에 지정. 이것이 root viewport와 교차되었을 때 callback 함수가 실행된다. 감시가 완료되면 뒷정리 함수안에서 disconnect해 관찰을 중지한다.
const onIntersect = useCallback(([entry]) => {
if (entry.isIntersecting) {
setPage((page) => page + 1);
}
}, []);
옵저버에서 실행될 콜백 함수, target 요소가 root viewport와 교차되었을 때 isIntersecting은 true가 되고, page state를 1씩 증가시킨다.
const getCardData = async (page) => {
const loadedCardData = await fetch(
`https://jsonplaceholder.typicode.com/comments?_page=${page}&_limit=10`
);
const response = await loadedCardData.json();
setCardData(cardData.concat(response));
};
useEffect(() => {
getCardData(page);
}, [page]);
useEffect의 의존성 배열 값으로 page를 받고 있으며, page값이 변경됐을 경우 getCardData 함수에서 fetch를 통해 API를 호출하고 있다.
결과물
참고링크
'프리온보딩' 카테고리의 다른 글
[POB] 기업과제 - 원티드 #4 (2) | 2021.08.17 |
---|---|
자바스크립트 동작원리 - 이벤트 루프 (7) | 2021.08.13 |
브라우저 동작 원리 알아보기 (2) | 2021.08.13 |
[POB] 기업과제 - 자란다 #3 (1) | 2021.08.07 |
[POB] 기업과제 -미스터카멜 #2 (3) | 2021.08.01 |