프로젝트를 진행하면서 API 콜을 통해 데이터들을 받아오는데 받아온 데이터를 화면에 보여주고 싶다. 그런데 한 번에 모든 데이터를 다 보여주는 것은 성능에 무리가 있다.(10000개를 한 번에? 렉 걸리겠죠) 그래서 있는 개념이 레이지 로딩이다.
레이지 로딩(lazy loading): 페이지를 읽어들이는 시점에 중요하지 않은 리소스 로딩을 추 후에 하는 기술
그래서 내 프로젝트에서는 API콜을 통해 서버에서 받아온 데이터 10개를 화면에 보여주고 스크롤을 내려서 10번째 데이터의 50퍼센트가 사용자 화면에 노출됐을 때 그 다음 10개를 추가로 API콜을 해서 화면에 보여주고 싶었다.
intersectionObserver API는 위 상황을 해결할 수 있는 API 이다.
간단한 사용방법을 보자면
let observer = new IntersectionObserver(callback, options);
위와 같이 할 수 있다. 객체를 선언하여 observer
를 만들어서 어떤 대상(element)을 target으로 정하고 observer.observe(target)
으로 관찰할 수 있다.
해당 target이 사용자 화면에 어느 정도 노출됐을 때 어떠한 행동을 할 수 있도록 하는 것이 기본 골자이다.
options 는 { root, rootMargin, threshold } 의 객체 형태이다.
여기서 내가 활용한 옵션 프로퍼티는 바로 threshold 이다. 이는 한계점이라는 사전적 정의가 있는데 소수점으로 백분율을 표현하면 target element의 몇 퍼센트가 노출됐을 때 콜백을 실행할지를 정할 수 있다.
callback 에서는 target element가 노출됐을 때 할 행동을 정의한다.
this.requestMoreResult.observe(this.videoList.lastChild);
우선
this.requestMoreResult
는new Observer(callback, options)
로 만든 observer 객체이다.
10개의 비디오를 처음에 화면에 보여준 후의 위 코드가 추가되는데 10개의 비디오리스트의 마지막 element를 target으로 설정한 코드이다.
이제 저 target element는 observe되는 대상이 됐다. 이제 target이 화면에 보여졌을 때 할 행동에 대해서 알아보자.
...
#handleScrollToLastItem() {
return new IntersectionObserver(
async (entries) => {
if (entries[0].isIntersecting) {
this.requestMoreResult.unobserve(this.videoList.lastChild);
this.#loadSkeleton(); //로딩이미지
const moreResult = await this.sendLoadMoreRequest(); //API호출
this.#renderSearchResult(moreResult); //새로운데이터 화면에 보여줌
}
},
{ threshold: 0.5 } //target이 50% 노출되면 콜백실행
);
}
...
위 코드의 return 되는 객체가 this.requestMoreResult 에 대입된다.
new 생성자 첫 번째 매개변수인 콜백함수를 살펴보면 entries에는 관찰되고 있는 target들의 리스트가 담긴다. 내 경우에는 하나만 observe 했으므로 해당 target이 entries[0]
에 담겨있다. 그 속성으로 isIntersecting
이 있는데 화면에 노출이 됐는지 여부를 boolean으로 알려준다.
그리고 이 프로젝트의 경우에는 마지막 데이터의 50%가 노출됐을 때 콜백을 실행해야하기 때문에 그 전에 관찰하고 있던 target은 unobserve
를 해준다. 그 이후에 로딩이미지를 보여주고 API 호출을 해서 이어지는 다음 데이터들을 받아온다. 그러고 화면에 보여주는 것으로 콜백 함수를 구성한다.