MongoDB 페이지네이션 구현 : Populate

henry·2024년 11월 5일

🚩 1. 페이지네이션을 위한 기본 세팅

skip, limit 사용

  • skiplimit을 사용하여 초기 랜더링 시 limit에 설정한 개수의 상품 조회
  • 이후, 더 보기 버튼을 누르면 skip 값을 증가시켜 새로운 상품 목록 조회
  • 예를 들어 한 번에 8개씩 상품을 불러오고 싶다면 limit을 8로 설정
  • skip은 처음에는 0에서 시작해서 더 보기 버튼을 클릭할 때마다 8씩 증가

클라이언트 측에서 상태 관리

const [skip, setSkip] = useState(0); // 조회할 데이터의 시작 위치

🚩 2. populate, sort, skip, limit 사용

상품을 페이지별로 조회하는 라우터 코드


const order = req.query.order ? req.query.order : 'desc';
const sortBy = req.query.sortBy ? req.query.sortBy : '_id';
const limit = req.query.limit ? Number(req.query.limit) : '20';
const skip = req.query.skip ? Number(req.query.skip) : 0;

let findArgs = {};
for (let key in req.query.filters) {
   if (req.query.filters[key].length > 0) {
      findArgs[key] = req.query.filters[key];
   }
}

const products = await Product.find(findArgs)
  .populate("writer")              // User 컬렉션에서 작성자 정보 조회
  .sort([[sortBy, order]])         // 정렬 
  .skip(skip)                      // skip 값을 사용해 특정 위치부터 조회
  .limit(limit);                   // limit 값만큼의 상품 수 제한
  • populate("writer")

    • writer 필드가 User 컬렉션의 _id를 참조하고 있어 User 컬렉션의 데이터를 함께 조회
    • 상품과 함께 작성자 정보(User 컬렉션의 필드)가 포함된 데이터
  • sort([[sortBy, order]])

    • 특정 필드를 기준으로 정렬
    const order = req.query.order ? req.query.order : 'desc';
     const sortBy = req.query.sortBy ? req.query.sortBy : '_id';
    • sortBy : _id 필드 기준
    • order : 내림차순
  • skip(skip)

    • skip 값만큼의 문서를 건너뛰고 조회
    • 더 보기 버튼을 누를 때마다 skip 값이 증가
    • 이전에 불러온 상품은 건너뛰고 새로운 상품 조회
  • limit(limit)

    • 한 번에 조회할 수를 제한

🚩 3. API 라우터

라우터에서 요청한 파라미터를 기준으로 페이지네이션 구현

router.get('/', async (req, res, next) => {
  const order = req.query.order ? req.query.order : 'desc';
  const sortBy = req.query.sortBy ? req.query.sortBy : '_id';
  const limit = req.query.limit ? parseInt(req.query.limit) : 10;
  const skip = req.query.skip ? parseInt(req.query.skip) : 0;

  try {
    const products = await Product.find(findArgs)
      .populate('writer')
      .sort([[sortBy, order]])
      .skip(skip)
      .limit(limit);

    const productsTotal = await Product.countDocuments();
    const hasMore = skip + limit < productsTotal;

    return res.status(200).json({
      products,
      hasMore,
    });
  } catch (err) {
    return res.status(400).json({ success: false, err });
  }
});
  • productsTotal = await Product.countDocuments()
    전체 상품 수

    • countDocuments()find()와는 달리 데이터를 가져오지 않고 해당 데이터의 개수만 조회
  • hasMore

    • skip + limit의 값이 전체 상품 수보다 적을 경우 true를 반환
    • 아직 조회할 데이터가 남아 있다는 의미

🚩 4. 예시


  • 현재 DB에 존재하는 상품의 수 : 9

  • 한 번에 조회할 개수를 8로 지정

  • 8개 상품 조회
  • hasMore : true 👉🏻 조회할 상품이 남아 있다는 의미
    • const hasMore = skip + limit < productsTotal ? true : false;

  • 더 보기 클릭 버튼 활성화 (더 조회할 상품이 존재하기 때문)

  • 더 보기 버튼 클릭 (limit으로 설정한 값 만큼 추가 조회)
    • 남은 상품은 1개이므로, 1개의 상품만 추가로 조회

0개의 댓글