intersection observer를 활용한 무한 스크롤

YOUNGJOO-YOON·2021년 5월 17일
0

react with webpack 5

목록 보기
25/37
post-custom-banner

TOC

  1. pseudo code
  2. 구현과 문제점
  3. 문제점의 해결

1. pseudocode

첫 아이디어는 이러하다.

기본적으로 react로 코드를 짜는 경우

useEffect(
const io=new IntersectionObserver((entries)=>{

    if (isIntersecting){
    callback();
    }
  })

,[isLoaded])
io.observe(loadMore)
...

useEffect 함수 내부에 fetch한 파일이 load가 된 후에 useRef로 지정해둔
loadMore가 vp내부에 존재하는 경우 callback 함수를 실행시킨다.

무한 스크롤을 구성하기 위해서는 이러한 구도가 생각된다.

<>
	<ArrayOfFetchedFile>
    <li>
    {ArrayOfLoadedFile} // array
    </li>
    </ArrayOfFetchedFile>
	<loadMoreDiv useRef={loadMore}>
    </div>
</>

ArrayOfLoadedFile은 배열 state이고 이 배열은 observe 내부 callback 함수가 실행될 때 마다 setState를 통해 초기화 해준다.

초기화를 하긴 하는데 setState(prev=>...prev,...fetchedFile)의 형태로
이전 값을 모두 포함하고 이후 값을 배열의 맨 뒤로 더해주는 형태를 취하도록 한다.

(이 부분에서 memo를 통해 최적화를 해주자)

그러면 ArrayOfLoadedFile 태그 내부에서는 배열이 계속 커지게 되고 배열이 커지고 이 배열이 화면에 그려지므로 observe 대상인 loadMoreDiv는 화면 밖으로 밀려나 callback 함수가 종료되게 된다.


2. 구현과 문제점

위 코드를 실제로 구현하고 나서 만난 문제점

1. 구조적 문제

위 코드는 구조적인 문제가 있다.

observe하고 있는 태그와 그 바로 위의 태그(윗태그라 하겠다)와의 관계인데 첫 화면 로드시 윗태그가 비어있는 경우 observe태그는 화면에 바로 노출되게 된다.

따라서 바로 callback 함수를 실행하게 된다.
(useEffect에 의해 조건이 있더라도 한 번은 실행)

그리고 화면에서 밀려날 때 까지 계속 callback 함수를 실행한다.

이 fetch 하고 있는 파일의 용량이 크다면 브라우저는 뻑이 가버린다.

따라서 이를 수정하기 위해서는 observe 대상을 바꾸어주어야 하거나 callback 조건을 더 까다롭게 수정해주어야 한다.

2. request의 문제

문제점 1과 함께 발생하는 문제인데 운 좋게 불러올 파일의 크기가 작아 observe가 화면에서 벗아나 callback 호출이 멈춘다고 해도 1번부터 콜백호출이 멈추기 전까지의 request 호출이 쌓여있다는 문제점도 존재한다.

callback 함수를 호출하는 것은 값이 싸기 때문에 이 명령은 계속 callStack에 쌓이게 된다. 이 호출은 fetching 이기 때문에 network 통신을 발생시키고 유저가 observe event를 발생시킨 경우 다시 callstack은 다 처리되지 못한채 쌓이게 된다.

컴퓨터가 좀 느리다면 이는 치명적인 에러를 뿜어내게 된다.


3. 문제점의 해결

개인적으로 이 문제점을 해결하기 위해 한 것.

필자는 처음에 위와 같은 방식으로 페이지를 구성했고 일단 작동한다는 것에 만족하였었다.

하지만 실제 사용하기에는 resource를 너무 많이 소모하고 원하는 바와 크게 차이가 있음을 인정하고 변경을 모색하였다.

아이디어는 이러하다.

우선 home 화면이 로드되면서 useEffect를 통해 fetcing을 시도한다.
성공하면 하위 컴포넌트에 값을 전달한다 (src) src를 전달받은 하위 컴포넌트는 useEffect를 통해 src값이 변화하는 순간 전달받은 src값을 그려낸다.

이 이미지 tag에 intersectionObserve를 걸어놓는다. 이미지가 다 로드되었다면 unobserve 해준다.

이미지 1은 이미지 2를 불러오고 이미지 1의 observe는 종료
이미지 2는 이미지 3을 불러오고 ...

이렇게 이미지는 이미지를 밀어내면서 화면 밖으로 밀려나가 observe는 동작하지 않는다.


구현

포폴용으로 사용할 사이트를 만들면서 작성중이기에 구현한 것을 올려본다.

이런식으로 화면이 넘어갈 때 마다 request가 발생하는 것을 확인해볼 수 있다.

profile
이 블로그의 글은 제 생각을 정리한 글과 인터넷 어딘가에서 배운 것을 정리한 글입니다. 출처는 되도록 남기도록 하겠습니다. 수정 및 건의 오류 등이 있으면 언제든지 댓글 부탁드립니다.
post-custom-banner

0개의 댓글