IntersectionObserver로 데이터 요청해보기

IntersectionObserver를 활용해 스크롤 위치에서 데이터 불러오기

2022-05-04

프로젝트를 진행하면서, 프로필 페이지에 유저정보와 포인트, 펫정보, 관심사 등 세로로 길게~~배치된 UI, 각각의 정보들을 서버에서 데이터를 하나하나 받아와 보여줘야 했다.

처음엔 아무생각없이 진행했다.

프로필 페이지에 진입했을 때 각각 필요한 데이터를 서버에 4번이나 요청했고, 그대로 컴포넌트에 그렸다.

그러다가💡 생각났는데,, 사용자에게 보이지않는 부분에 데이터도 받아오고 있었다.

굳이 스크롤을 내리지도 않고 사용자에게 보이지도 않는 부분에 데이터까지 받아올 필요는 없었다.

그럼 사용자가 스크롤을 내려 보고자하는 부분에 도달했을때, 아니면 도달하기 직전에 데이터를 불러와 보여주면 어떨까 싶었다.

이전에 강의에서 이미지 Lazy로딩을 배웠었는데, 이미지 대신에 데이터 요청을 해보면 어떨까 생각했다.

post image

컴포넌트가 마운트 되자마자 모든 데이터들이 요청된다.

우선 훅을 하나 만들었다. ref객체가 감지되면 loaded가 true로 바뀌고, 더이상 감시가 중지된다.

export const useLazyRequest = () => {
  const ref = useRef(null) as MutableRefObject<HTMLDivElement>
  const [loaded, setLoaded] = useState<boolean>(false)

  useEffect(() => {
    const options = {}
    const callback = (entries, observer) => {
      entries.forEach((entry) => {
        console.log(entry)
        if (entry.isIntersecting) {
          console.log('is Intersecting')
          setLoaded(true)
          observer.unobserve(entry.target) // 한번만 요청되도록 감시 중지
        }
      })
    }
    const observer = new IntersectionObserver(callback, options) // 객체 생성하기
    observer.observe(ref.current)
  }, [])

  return {ref, loaded}
}

사용하고자 하는 컴포넌트로 돌아와서,

나는 데이터 요청에 SWR을 사용했다.

https://swr.vercel.app/ko


// SWR
export const useUserKeywords = (loaded: boolean) => {
  const {data, isValidating, error} = useFetch(loaded ? PATH + '/keywords' : null, {
    revalidateOnFocus: false,
    revalidateIfStale: false,
    shouldRetryOnError: false
  })

  return {
    userKeywords: data,
    isValidating,
    error
  }
}

SWR은 위처럼 설정했다, SWR자체도 hook이기 때문에 useEffect나 다른 함수안에서 사용하지 못한다.

const {ref, loaded} = useLazyRequest()
const {userKeywords, isValidating, error} = useUserKeywords(loaded)

<Contents ref={ref}>
        {isValidating ? (
          <Loading />
        ) : (
          <>
           {...}
          </>
        )}
</Contents>

4개의 섹션이 있는데, 페이지 진입시 1, 2번까지만 사용자에게 보이고 3, 4번의 컴포넌트를 위처럼 적용했다.

ref에 사용자의 view가 도달하면 userKeywords를 요청해 데이터를 받아온다.

post image

과거에는 getBoundingClientRect() 를 사용해 구현했다고 하는데, 리플로우 현상이나 성능면에서 보완하고자 요즘엔 intersection Observer를 사용해 타겟을 관찰한다고 한다.

또 무한스크롤도 구현해 볼 수 있다. 페이지의 맨 마지막 요소에 도달했을 때, 요청하는 페이지 쿼리를 ++ 하면 쉽게 구현할 수 있다.

다른 필요한 페이지에 적용해봐야겠다!