한번에 데이터를 모두 불러오는 것이 아닌,
화면을 스크롤할 때마다 데이터를 추가로 불러오는 Intinite Scroll을 구현해 보았다.
Infinite Scroll 구현 방법
- scroll event: 스크롤이 끝까지 내려가는 경우 데이터 추가로 불러오도록 구현하는 방법
throttle 등을 추가로 구현해 최적화 할 필요가 있음 - Intersection Observer API 사용
찾아보니 Intersection Observer API를 활용한 예제가 많고 편리한 듯 하여 Intersection Observer를 사용하기로 했다.
일부 브라우저에서는 Intersection Observer 지원이 안 된다고 하지만, Explorer 외에는 거의 지원이 되는 것 같다.
Explorer는 MS에서도 지원을 종료하고 있고,
지원이 되지 않는 브라우저를 위한 Intersection Observer Polyfill도 있으니 사용에 문제는 없을 것 같다.
(지원 브라우저는 아래 링크의 Browser Compatibility를 참고)
developer.mozilla.org/ko/docs/Web/API/IntersectionObserver
아직 React 초보라 React Hook은 공부를 안 했는데...
React Hook을 사용한 예제가 많아서 한참 헤매다 Hook을 사용하지 않고 구현했다.
Intersection Observer의 원리를 대략 설명하면 이렇다.
화면 안에 어떤 target을 정해서 observer가 관찰하고 있다가
그 target이 어떤 기준을 충족하면 callback 함수를 실행하고,
이 callback 함수에서 내가 원하는 동작(데이터 추가로 불러오기)을 하도록 한다.
나는 화면 아래로 스크롤하다가 데이터가 끝나는 부분(화면 하단)을 만나면 데이터를 추가로 불러오는 것이 목적이다.
이를 위해 화면 하단에 target으로 삼을 <div> 태그를 만들고 Observer가 이 <div>태그를 관찰하도록 연결시키면,
화면에 내가 지정한 기준(options)을 만족하는 target(<div>)이 나타날 때 데이터를 추가로 불러오는 callback 함수를 실행시킨다.
모르는 것이 많아 ref는 어디에서 만들어야 되는지 등 정말 기본적인 것부터 헤맸어서.. 기록해둔다.
구현한 코드
1. constructor에서 React.createRef()로 ref를 생성한다.
constructor(props) {
super(props);
this.targetRef = React.createRef();
}
2. target으로 삼을 <div> 태그를 화면 하단에 만들기
이때 ref에 this.targetRef를 전달한다.
render() {
return (
<div>
<div ref={this.targetRef}></div>
</div>
);
}
3. Intersection Observer 생성해 target을 observe()로 연결하기
componentDidMount()에서 _createObserver() 함수를 호출해 Intersection Observer를 생성하도록 했다.
componentDidMount() {
this._createObserver();
}
_createObserver() {
let observer;
// observer의 option을 설정
let options = {
root: null,
rootMargin: '0px 0px 20px 0px',
threshold: 0,
};
// observer 객체를 생성하면서 callback함수와 option을 전달
observer = new IntersectionObserver(this._checkIntersect, options);
// target을 설정
let target = this.targetRef.current;
// target을 observe()
observer.observe(target);
};
4. Intersecting 시 실행할 동작을 callback 함수에 넣어주기
여기서 entry.isIntersecting을 사용했는데, 이외에도
entry.boundingClientRect, entry.intersectionRatio, entry.intersectionRect,
entry.rootBounds, entry.target, entry.time 등이 있다.
// observe에 전달한 callback 함수
_checkIntersect = (entries, observer) => {
entries.forEach(entry => {
// Intersecting이 발생하면 _fetchItems() 함수를 호출
if (entry.isIntersecting)
this._fetchItems();
});
};
5. _fetchItems()에서 데이터를 추가로 불러온다.
※ 잘못된 내용이 있으면 수정하겠습니다.
참고한 글
- developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
- scotch.io/tutorials/infinite-scroll-in-react-using-intersection-observer
- egg-programmer.tistory.com/275
throttle 관련 참고할만한 글
'프로그래밍 > React' 카테고리의 다른 글
[React] 2. GitHub 저장소 만들고 프로젝트 푸시하기 (0) | 2022.09.07 |
---|---|
[React] SPA vs MPA (0) | 2022.06.05 |
[React] React에서 Axios 사용해 API 호출하기 (0) | 2022.06.05 |
[React] 1. React 프로젝트 생성하기(create-react-app) (0) | 2022.03.20 |
댓글