[JS] Vanilla JS로 라이브러리없이 무한스크롤 구현하기

녕녕·2023년 5월 16일
1

JavaScript🍰

목록 보기
2/6
post-thumbnail

영화 검색 사이트를 만드는데 무한스크롤을 구현하게 됐다. 그 과정에서 알게된 것들을 기록해두려고 한다.

⌛️ 이벤트리스너와 디바운스

📌 이벤트리스너

  • scroll 되면 이벤트가 발생하도록 한다.
  • scroll 이벤트는 일어날 확률이 많은 이벤트이다. 따로 처리를 해주지 않는다면, 아래 예시의 콘솔창처럼 scroll이 동작할 때마다 함수가 동작하여 성능 문제가 발생할 수 있다.

const test = async () => {
  console.log('api 호출!');
};

// 스크롤 이벤트
document.addEventListener('scroll', test);

📌 디바운스

  • 위와 같은 경우에서 이벤트를 제어하기 위해 디바운스를 사용한다.
  • 아래의 콘솔창을 보면 위와 달리 디바운스 함수로 처리해줘서 api가 일정 시간이 지난 후에 한번만 호출된다.

const infinite = async () => {
  console.log('api 호출!');
};

// 디바운스(마지막 호출함수만 실행)
let timer = null;
const debouncing = () => {
  //스크롤할 때마다 타이머 재설정
  if (timer) clearTimeout(timer);
  timer = setTimeout(infinite, 500);
};

// 스크롤 이벤트
document.addEventListener('scroll', debouncing);
  • 즉 디바운스는 사용자가 여러번 입력 또는 호출하더라도 코드를 한번만 실행되도록 하는 함수이다. 특정 시간 동안 호출된 것은 처리하지 않는다.
  • 코드로 구현한 방법을 살펴보자
    • 스크롤 한번이 실행될 때, timer=null이므로 조건문 내의 코드를 실행하지 않고 timer에 setTimeout을 할당한다. 스크롤이 연속적으로 여러번 실행되면, 맨 처음에 timer에 할당된 것은 초기화 되고 다시 setTimeout이 실행되는 것이 여러번 반복된다. 여기서 500ms 가 지나지 않았다면 setTimeout 내의 콜백함수는 한번도 실행되지 않았다.
    • 이런 방법으로 가장 마지막에 호출된 debouncing 함수에서 timer에 setTimeout이 할당되고, 500ms가 지나면 무한스크롤 함수가 한번 실행된다.

⌛️ 무한스크롤

  // 무한스크롤
  const infinite = async () => {
    if (
      searchInputEl.value &&
      window.innerHeight + window.scrollY >= document.body.offsetHeight
    ) {
      countPages++;
      searchData(searchInputEl.value, selectYearEl.value, countPages);
    }
  };
  • 무한스크롤이란 말그대로 스크롤을 무한히 내릴 수 있는 사용자 경험 방식을 말한다.
  • 문서의 최하단에 사용자가 보고 있는 브라우저창이 위치할 때를 조건으로 뒀다.
  • 조건을 충족하면 변수 countPages의 수를 늘리고, api에 변수를 인자로 넣어주며 api를 호출하는 코드를 짰다. 이때 페이지가 하단에 도달했을 때를 조건으로 말할 수 있다.

📌 너비 및 높이 프로퍼티

  • 조건을 브라우저가 이해할 수 있게 코드로 어떻게 표현했을까.
  • 창의 높이와 너비를 활용했다. 이때 다양한 속성들이 있는데, 자세한 속성 설명은 [Javascript] 브라우저의 창에 대한 이해를 참고했다.
  • 이 중에서 innerHeight(메뉴바, 툴바 제외한 안쪽 창 영역의 높이와 너비), scrollY(전체 컨텐츠를 얼마나 스크롤했는가에 대한 값), offsetHeight(기준점 기준으로 왼쪽과 위에서 얼마나 떨어져있는 가에 대한 값)을 활용했다.

  • 이미 렌더링 되어있는 document.content가 있다.
  • window.innerHeight 보라색 영역이 보고 있는 브라우저 창이다. 처음엔 document.content의 최상단에 위치했지만, scroll을 내리면서 맨 아래로 내려오게 됐고, 동시에 window.scrollY의 값이 증가했을 것이다.
  • 즉, 화면이 document의 최하단에 위치할 때 api 호출 함수를 동작시킬 것이고 그것이 window.innerHeight + window.scrollY의 값이 document.body.offsetHeight보다 같게되는 지점이다.
  • api가 호출될 때마다 렌더링되면서 docuement가 길어지니 document.body.offsetHeight의 값은 증가할 것이다. 사용자가 더 많은 정보를 보려고 아래로 스크롤 할 때마다 window.scrollY의 값도 증가할 것이다. 이러한 값 변화에 따라 조건을 충족시키며 무한스크롤이 동작하도록 했다.

⌛️ 무한스크롤 API 및 라이브러리 사용

이렇게 API와 라이브러리 사용없이 무한스크롤을 구현하고나니, 예상했던 것보다 코드의 양이 적고 간단하다고 생각했다. 그러고나니 API와 라이브러리를 왜 사용하는지 의문이 들었다.

  • 찾아보니 debounce, throttle이 성능을 개선해줄지 언정, 근본적으로 불필요한 이벤트가 발생하는 것은 여전하다는 문제점이 계속 남아있기 때문이었다.
  • 다음엔 Intersection Obsever API 또는 라이브러리를 사용하여 무한스크롤을 구현해봐야겠다.

참고

profile
FE Developer | 차근차근

0개의 댓글