상똥이의 Back-End 공부방

[Nest.js] 페이지네이션 백엔드 구현 (prisma) + 프론트 구현 본문

Nest.JS

[Nest.js] 페이지네이션 백엔드 구현 (prisma) + 프론트 구현

상똥백 2024. 7. 4. 01:03

목표
- 백엔드에서 페이지네이션을 위한 로직을 구현한다
- n번째 페이지에 보여줄 데이터 수(limit)를 설정할 수 있다
- 데이터는 생성된 시간을 기준으로 내림차순 정렬한다
 
목차
0. 초기 설정 (데이터베이스, 초기 데이터, 데이터 타입)
1. 기능 구현
2. 포스트맨으로 확인

 


[0. 초기 설정]

1. 데이터베이스
- 예시로 댓글 타입을 활용했다
- 프리즈마를 사용해 간단히 구현한다
- 댓글 id(자동생성, 정수타입), 닉네임, 내용, 생성일자

model Comment {
  id        Int      @id @default(autoincrement())
  nickname  String
  content   String
  createdAt DateTime @default(now())
}

 
2. 초기 데이터
- 총 42개의 댓글을 생성해두었다

 


[1. 기능 구현]

1. service
(1) findAll
- take : 최소 1개 이상의 레코드를 가져오기 위해 limit과 1 중 큰 값을 사용
- skip : 이미 렌더링된 데이터의 수, 현재 페이지와 페이지당 데이터 수(take)를 기반으로 계산
- findMany : createdAt 필드를 기준으로 내림차순 정렬(최신순 정렬), 페이지네이션을 위해 take와 skip으로 반환되는 데이터 수를 제어
(2) countAll 
- 데이터 개수를 반환한다
- 페이지네이션 구현 시 페이지 버튼을 만들기 위해 사용된다

// src/domain/comment/comment.service.ts

import { Injectable } from '@nestjs/common';
import { CreateCommentDto } from './comment.dto';
import { PrismaService } from 'src/database/prisma/prisma.service';

@Injectable()
export class CommentService {
  constructor(private readonly prismaService: PrismaService) {}

  async findAll(page: number, limit: number) {
    const take = Math.max(limit, 1);
    const skip = (page - 1) * take;

    return await this.prismaService.comment.findMany({
      orderBy: { createdAt: 'desc' },
      take,
      skip,
    });
  }
  
  async countAll() {
    return await this.prismaService.comment.count();
  }
}

 
2. controller
- findAll : 쿼리를 통해 page와 limit을 받음, 이때 쿼리는 기본 타입이 string이므로 ParesIntPipe를 사용

import {
  Controller,
  Get,
  Post,
  Body,
  Query,
  ParseIntPipe,
} from '@nestjs/common';
import { CommentService } from './comment.service';
import { CreateCommentDto } from './comment.dto';

@Controller('comment')
export class CommentController {
  constructor(private readonly commentService: CommentService) {}

  @Get()
  findAll(
    @Query('page', ParseIntPipe) page: number,
    @Query('limit', ParseIntPipe) limit: number,
  ) {
    return this.commentService.findAll(page, limit);
  }
  
  @Get('count')
  count() {
    return this.commentService.countAll();
  }
}

[2. 확인]

- 아래와 같이 page와 limit값에 따라 올바르게 반환되는 것을 볼 수 있다.
- page=1, limit=5

- page=2, limit=3

 
페이지네이션 프론트 코드는 아래에서 확인할 수 있다
페이지네이션 - 페이지 기반

페이지네이션 - 무한스크롤