페이지 처리 방법에 관한 고찰

✒️ 2025-05-28 10:00 내용 수정



1. 새 페이지 번호마다 API로 DB에 요청하기

// chatgpt 예시코드
import React, { useState, useEffect, useRef } from 'react';

const App = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1);
  const [loading, setLoading] = useState(false);
  const observerRef = useRef();

  useEffect(() => {
    fetchData(page); // 페이지가 바뀔 때마다 api 요청
  }, [page]);

  const fetchData = async (page) => {
    setLoading(true); // 데이터 가져오기 전 로딩 처리
    try { // 예시로 데이터를 가져오는 코드
      const response = await fetch(`https://api.example.com/data?page=${page}&limit=10`);
      const newData = await response.json();
      setData(prevData => [...prevData, ...newData]); // 기존 데이터 + 새 데이터로 표시
    } catch (error) {
      console.error("Failed to fetch data:", error);
    } finally {
      setLoading(false);
    }
  };

  const handleObserver = (entries) => { // 스크롤이 넘어가면 새 페이지로 처리
    const target = entries[0];
    if (target.isIntersecting) {
      setPage(prevPage => prevPage + 1);
    }
  };

  useEffect(() => {
    const option = {
      root: null,
      rootMargin: "20px",
      threshold: 1.0
    };
    const observer = new IntersectionObserver(handleObserver, option);
    if (observerRef.current) observer.observe(observerRef.current);

    return () => {
      if (observerRef.current) observer.unobserve(observerRef.current);
    };
  }, []);

  return (
    <div>
      <h1>Infinite Scroll with Intersection Observer</h1>
      <div>
        {data.map((item, index) => (
          <div key={index} className="item">
            {item.name}
          </div>
        ))}
      </div>
      {loading && <p>Loading...</p>}
      <div ref={observerRef} style={{ height: '20px', backgroundColor: 'lightgray' }} />
    </div>
  );
};

export default App;

2. 데이터를 먼저 받아온 후 Array.slice()로 처리하기

// chatgpt 예시 코드
import React, { useState, useEffect } from 'react';

const App = () => {
  const [data, setData] = useState([]);
  const [visibleData, setVisibleData] = useState([]);
  const [page, setPage] = useState(1);
  const itemsPerPage = 20;

  useEffect(() => {
    const fetchData = async () => {
      // 한 번에 모든 데이터를 가져옴
      const result = await fetch('https://api.example.com/data').then(res => res.json());
      setData(result); // 데이터를 저장
      setVisibleData(result.slice(0, itemsPerPage)); // 표시할 데이터를 따로 저장
    };

    fetchData();
  }, []);

  const loadMore = () => { // 더보기 처리
    setPage(prevPage => {
      const newPage = prevPage + 1; // 다음 페이지
      const start = (newPage - 1) * itemsPerPage; // 데이터 시작점(offset)
      const end = newPage * itemsPerPage; // 가져올 데이터 범위(length)
      setVisibleData(prevData => [...prevData, ...data.slice(start, end)]); // 표시할 데이터를 수정
      return newPage;
    });
  };

  return (
    <div>
      <h1>Load More Example</h1>
      <div>
        {visibleData.map((item, index) => (
          <div key={index} className="item">
            {item.name}
          </div>
        ))}
      </div>
      <button onClick={loadMore}>Load More</button>
    </div>
  );
};

export default App;