Infinite scroll 구현하기

Yujin·2023년 5월 9일
0

Infinite scroll은 사용자가 스크롤을 내리면 추가적인 콘텐츠를 동적으로 로드하는 기술입니다.

Infinite scroll 기법을 사용하는 방법

1. 이벤트 리스너 등록

스크롤 이벤트를 감지하고 추가 콘텐츠를 가져오기 위해 이벤트 리스너를 등록합니다.

window.addEventListener('scroll', loadMoreContent);

2. API 호출

추가 콘텐츠를 가져오기 위해 서버 API를 호출합니다. 이때 비동기적으로 호출하며, 새로운 데이터를 로드할 때마다 페이지 번호 또는 커서 위치 등을 파라미터로 전달합니다.

function loadMoreContent() {
  if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
    const nextPage = currentPage + 1;
    const url = `https://api.example.com/content?page=${nextPage}`;

    fetch(url)
      .then(response => response.json())
      .then(data => {
        // 가져온 데이터를 처리합니다.
        // DOM 요소를 생성하여 새로운 콘텐츠를 추가합니다.
        // ...
        // 현재 페이지 번호를 업데이트합니다.
        currentPage = nextPage;
      })
      .catch(error => console.error(error));
  }
}

3. 새로운 콘텐츠 추가

가져온 데이터를 처리하여 DOM에 새로운 콘텐츠를 추가합니다.

function loadMoreContent() {
  // ...

  fetch(url)
    .then(response => response.json())
    .then(data => {
      // 가져온 데이터를 처리합니다.
      const newContent = createNewContent(data);

      // DOM 요소를 생성하여 새로운 콘텐츠를 추가합니다.
      const container = document.querySelector('#content-container');
      container.appendChild(newContent);

      // ...

    })
    .catch(error => console.error(error));
}

4. 다음 페이지 번호 업데이트

새로운 콘텐츠를 추가한 후, 다음 페이지 번호를 업데이트합니다.

function loadMoreContent() {
  // ...

  fetch(url)
    .then(response => response.json())
    .then(data => {
      // 가져온 데이터를 처리합니다.

      // ...

      // 현재 페이지 번호를 업데이트합니다.
      currentPage = nextPage;
    })
    .catch(error => console.error(error));
}

5. 마지막 콘텐츠에 도달했을 경우 이벤트 리스너 지우기

마지막 콘텐츠에 도달하여 스크롤 이벤트 리스너가 필요 없어진 경우, 이벤트 리스너를 지웁니다.

if (total === end) {
  window.removeEventListener('scroll', loadMoreContent)
  return
}

Infinite scroll 구현

아래에서 사용하는 외부 API 👉🏻 https://jsonplaceholder.typicode.com/

총 100개의 데이터를 한 페이지에 10개씩 로드하면서, scroll이 바닥에 도달할 경우 페이지를 +1 하며 10개의 데이터를 더 로드한다.

1. 필요한 전역 변수 선언

let currentPage = 1;
let total = 10;
const limit = 10;
const end = 100;

const $posts = document.querySelector('.posts');

2. 이벤트 리스너 등록

window.addEventListener('load', () => {
  loadPosts(currentPage, limit);
});
window.addEventListener('scroll', handleScroll);

3. API 호출

const getPosts = async (page, limit) => {
  const API_URL = `https://jsonplaceholder.typicode.com/posts?_page=${page}&_limit=${limit}`
  const res = await fetch(API_URL);
  
  if (!res.ok) {
    throw new Error('에러가 발생했습니다.');
  }
  return await res.json();
}

const loadPosts = async (page, limit) => {
  const res = await getPosts(page, limit);
  showPosts(res);
}

4. 새로운 콘텐츠 등록

const showPosts = (posts) => {
  posts.forEach((post) => {
    const $post = document.createElement('div');
    $post.classList.add('post');
    $post.innerHTML = `
      <div class="header">
        <div class="id">${post.id}</div>
        <div class="title">${post.title}</div>
      </div>
      <div class="body">${post.body}</div>
    `
    $posts.appendChild($post);
  })
}

5. scroll에 따른 동작 지정

onst handleScroll = () => {
  const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
  
  if (scrollTop + clientHeight >= scrollHeight) {
    currentPage++;
    total += 10;
    loadPosts(currentPage, limit);
    return;
  }
}

6. scroll 이벤트 리스너 삭제

const handleScroll = () => {
  ...
  if (total === end) {
    window.removeEventListener('scroll', handleScroll);
    return;
  }
  ...
}

Infinite scroll 구현 결과

데이터 100개를 다 로드한 경우, scroll 이벤트 리스너를 삭제했다.

profile
_〆(・_・。)

0개의 댓글