Blog

[NestJS] 13. 게시글 페이징(Pagenation)과 무한스크롤(Infinity Scroll)

Category
Author
citeFred
citeFred
PinOnMain
1 more property
NestJS, TypeORM 이해하기
Table of Content

1. 페이징 기능 추가

article.service.ts
페이징 처리를 위해서는 쿼리스트링(Param)으로 페이지와 게시글 수를 받아와야 한다.
getPaginatedArticles(page: number, limit: number) 메서드 명으로 위 두개의 파라미터를 받아온다.
page : 현재 페이지 번호(1,2,3,…)
limit : 한 개의 페이지당 보여줄 게시글의 수
skip : (page - 1) * limit 를 통해 이전 페이지에서 가져왔던 게시글을 건너뛰기 위한 변수
ex) 2페이지로 접근하면, (2-1) * 10 = 9개 를 건너 뜀
TypeORM의 find() 메서드의 페이징 인터페이스 활용
find() 메서드는 skiptake를 함께 사용하면 페이징이 구현됨
... import { UserRole } from 'src/user/user-role.enum'; @Injectable() export class ArticleService { private readonly logger = new Logger(ArticleService.name); // Logger 인스턴스 생성 constructor( @InjectRepository(Article) private articleRepository: Repository<Article> ){} ... // 전체 게시글 조회 ... // 페이징 추가 게시글 조회 기능 async getPaginatedArticles(page: number, limit: number): Promise<Article[]> { this.logger.verbose(`Retrieving paginated articles: page ${page}, limit ${limit}`); const skip: number = (page - 1) * limit; const articles = await this.articleRepository.find({ skip, take: limit, order: { createdAt: 'DESC' } // 내림차순 }); this.logger.verbose(`Paginated articles retrieved successfully`); return articles; } // 나의 게시글 조회 ... }
TypeScript
복사
article.controller.ts
getPaginatedArticles( @Query('page') page: number = 1, @Query('limit') limit: number = 10 ) 라는 메서드에 page, limit 두개의 파라미터를 쿼리스트링으로 받아온다.
특별한 입력이 없는 경우에도 기본값으로 1페이지, 10개 게시글을 볼 수 있도록 기본값 설정
Service 계층의 getPaginatedArticles() 메서드에 인수로 page, limit을 전달하며 호출
게시글 배열 결과를 DTO로 변환하고, 메시지, 상태코드 등과 함께 ApiResponseDto에 맞춰 클라이언트로 응답하게 된다.
... import { ArticleResponseDto } from './dto/article-response.dto'; @Controller('api/articles') @UseGuards(AuthGuard('jwt'), RolesGuard) // JWT 인증과 role 커스텀 가드를 적용 export class ArticleController { private readonly logger = new Logger(ArticleController.name); // Logger 인스턴스 생성 // 생성자 주입(DI) constructor(private articleService: ArticleService){} ... // 전체 게시글 조회 기능 ... // 페이징 처리된 게시글 조회 @Get('/paginated') async getPaginatedArticles( @Query('page') page: number = 1, @Query('limit') limit: number = 10 ): Promise<ApiResponse<ArticleResponseDto[]>> { this.logger.verbose(`Retrieving paginated articles: page ${page}, limit ${limit}`); const articles = await this.articleService.getPaginatedArticles(page, limit); const articleDtos = articles.map(article => new ArticleResponseDto(article)); this.logger.verbose(`Paginated articles retrieved successfully`); return new ApiResponse(true, 200, 'Paginated articles retrieved successfully', articleDtos); } // 나의 게시글 조회 기능 ... }
TypeScript
복사
POSTMAN을 통한 테스트
1페이지를 조회하는 경우
29~20번까지 10개 게시글 조회
2페이지를 조회하는 경우
첫페이지(29~20번) 이후인 19~10번까지 10개 게시글 조회

2. 프론트엔드 무한스크롤 참고 자료

프론트엔드에서 무한 스크롤 요청하기 위한 참고자료
위 서버 코드를 통해 백엔드 API는 페이지가 증가하는 것에 대해서 계속해서 다음 페이지의 게시글들을 반환할 준비가 되어있다.
프론트엔드는 백엔드 API에 요청 할 때 다음과 같은 예시로 page를 1씩 증가시키는 로직이 필요하다.
아래 예시는 jQuery의 Ajax 요청 코드로 구성되어 있다. 필요 시 동일한 로직으로 Fetch Api 또는 HttpClient로 구현코드를 변경해도 된다.
변수는 page = 1, limit = 10으로 초기화 되어 있다.
let: 변수의 값을 변경할 수 있는 경우에 사용
const: 변수의 값을 한 번 설정하면 변경할 수 없는 경우에 사용
브라우저의 scroll 에서 특정 높이에 다다를때마다 loadArticles() 함수를 호출되고 있다.
요청 시 마다 page, limit 변수에 할당된 값을 쿼리스트링 데이터로 전달하고 있다.
이 요청은 /api/articles/paginated?page=1&limit=10 과 같다.
요청에 성공하면 게시글을 붙여넣는 추가 로직이 구성되어야 한다.
이후 초기화된 page의 값을 증가시킨다(1→2)
let page = 1; const limit = 10; function loadArticles() { $.ajax({ url: `/api/articles/paginated`, method: 'GET', data: { page: page, limit: limit }, success: function(response) { // DOM에 게시글 추가 const articles = response.data; // 응답 구조에 맞게 조정 articles.forEach(article => { // 게시글을 목록에 추가 }); page++; }, error: function(xhr, status, error) { console.error('게시글을 가져오는 중 오류 발생:', error); } }); } // 초기 게시글 로드 loadArticles(); // 스크롤 시 더 많은 게시글 로드 $(window).on('scroll', () => { if ($(window).scrollTop() + $(window).height() >= $(document).height()) { loadArticles(); } });
TypeScript
복사
기본적으로 이런 흐름의 스크립트가 필요하며 선택된 프레임워크에 따라 코드를 튜닝하여 사용할 수 있다.
백엔드+프론트엔드 무한스크롤 구현 예시 모습
Search
 | Main Page | Category |  Tags | About Me | Contact | Portfolio