Spring

[Spring + Javascript] 게시물 목록 페이지네이션 구현하기(6)

jongh0 2025. 6. 27. 20:43

 

해당 게시물에서는 게시물목록을 출력할 때, 페이지를 구분해서 게시물 n개씩 나눠서 보여줄 수 있도록 하는

페이지네이션 기능에 대해서 알아보자 

 

일단 페이지네이션이 어떤식으로 구현되는지 확인하기 위해서 티스토리 블로그 목록을 참조하였다.

 

tistory 페이지네이션

 

해당 페이지는 내 티스토리 게시물 목록의 페이지 네이션이다. 내 티스토리 테마에서는 10개의 게시물씩 페이지를 나눠 놓았고,

총 22개의 게시물을 3개의 페이지에 10개 / 10개 / 2개 나누어서 페이지가 구성 되어있다.

 

일단 가장 최근에 적었던 게시물이 1페이지 상단에 오도록 되어있으므로, DB에 게시물이 저장될 때, 고유키 글 번호가 1씩 오르는 시퀀스로 구성되어있다면, 글번호 값을 내림차순으로 정렬해서 게시물을 사용자에게 보여주면 된다.

 

2페이지

 

2페이지를 눌렀을때, 10개의 게시물이 출력되고 url을 확인했을 때, ?page=2라는 파라미터 키워드가 추가된 것을 확인할 수 있다. 즉, page라는 파라미터에 n이라는 값이 담겨있을 때, n페이지 게시물 목록에 대해서 사용자에게 보여준다.

 

게시물 상세조회

 

게시물 상세조회

 

그리고 내 티스토리 주소 뒤에 숫자 하나(n)를 통해서 요청을 보내게 되면, 내 티스토리에 n번째 글 상세페이지를 보여준다. 

 

그러면 배웠던 스프링과 자바스크립트를 통한 서버와 브라우저간에 요청방식을 구분해보자.

  • 게시물 목록 페이지 : com/?page=2 와 같이 브라우저가 요청을 보내면 @RequestParam 으로 서버측에서 값을 응답받음
  • 게시물 상세페이지 : com/3 와 같이 단순히 링크뒤에 문자열을 통해 요청을 보내면 서버측에서 @PathVariable 을 통해 값을 응답받음

 

  어떤식으로 티스토리 페이지가 브라우저 요청과 서버측에서 어떤식으로 요청에 대한 데이터를 받아들이는지 파악하였다.

이전에 상세페이지는 @PathVariable 어노테이션을 통해서 어떤식으로 구현되는지 작성한 적이 있으니 게시물 목록 페이지를 @RequestParam 어노테이션으로 처리할 수 있도록 구현해보자.

 

[페이지네이션 알고리즘 구현하기]

 

PageVo 필드

 

 

 

페이지네이션을 위한 PageVo 클래스이다. 여기서 가장 중요한 부분은 페이지네이션을 위해서 어떤 필드가 필요하고

해당 필드가 어떤 로직을 통해서 값이 할당되는지를 알아야한다.

 

일단 아래 생성자 오버라이딩된 4개의 필드 파라미터만 사용하는 PageVo를 살펴보자.

 

무조건 PageVo 객체가 만들어져 올바르게 작동하기 위해서 필요한 4개의 파라미터는

 

1. 전체 글개수

2. 현재페이지

3. 한 페이지에 몇 개의 페이지를 보여줄지

4. 한 페이지에 몇 개의 게시물을 보여줄지

 

해당 4개의 파라미터만 있으면 나머지 필드 4개는 아래와 같은 식으로 값을 할당받을 수 있다.

수학시간은 아니므로 알고리즘에 대한 설명은 건너뛰겠다. (식 자체를 이해하기보다는 현재페이지가 몇 페이지고 글 5개마다 10개의 페이지로 나눴다라고 예시를 들며 식에 대입하면서 이해하기가 편했습니다.)

 

list.jsp

 

 

일단 게시물 목록이 출력될 <tbody> 태그에 id로 tb를 지정해두고 전체 테이블 밖에 <div>태그를 통해서 

페이지 번호 버튼들을 출력해줄 공간을 만들어 두었다.

 

BoardApiController list() 메서드

 

 

 BoardApiController 클래스는 @RequestMapping 어노테이션을 통해서 api/board 키워드가 요청 접두사로 지정되어 있다.

그리고 메서드 파라미터에 (@RequestParam int page)를 통해서 브라우저가 요청을 보낼 때 page라는 파라미터에 값을 담아 보내게 되고 서버측에서 해당 어노테이션을 통해서 page 번호를 받을 수 있다.

 

 그래서 @GetMapping()과 같이 파라미터를 비워두면 127.0.0.1:8080/api/board/?page=3 과 같은 요청이 GET 방식으로 요청이 서버로 들어오면 해당 메서드가 실행되는 구조로 되어있다.

 

일단 아까 페이지네이션 알고리즘이 구현되어있는 PageVo 클래스 객체에 생성자로 필요한 4개의 파라미터가 있었다.

 

1. currentPage : 사용자가 요청을 보낼때 파라미터로 보내준 page (@RequestParam 어노테이션으로 받아옴)

2. listCount : getBoardCnt() 메서드를 만들어서 현재 몇개의 글이 존재하는지 할당

3. pageLimit : 내가 직접 지정 (한 번에 몇개의 페이지를 보여줄지?)

4. boardLimit : 내가 직접 지정 (한 페이지에 몇개의 게시물을 보여줄지?)

 

 

listCount는 Mapper에서 다음과 같은 sql 구문으로 전체 글 개수를 반환받을 수 있다.

 

 

 이제 PageVo 생성자를 통해서 객체를 생성하면 해당 객체에는 페이지네이션에 필요한 8개의 필드에 값이 모두 할당된다.

그리고 해당 객체를 DB에서 게시물 리스트를 출력할 list() 메서드에 파라미터로 넣어준다.

 

근데 여기서 기존에 모든 글목록을 출력하는 쿼리문이 아니라 한페이지에 몇 개의 게시물을 보여줄지에 대한 추가 쿼리문이 필요하다.

 

 

 

OFFSET #{offset} ROWS FETCH NEXT #{boardLimit} ROW ONLY 이라는 구문이 추가되었다

이 구문은 #{offset} 만큼 떨어진 결과에서 #{boardLimit} 개의 행을 출력해줘 라고 볼 수 있다.

 

그래서 해당 쿼리문은 내가 요청을 보낼 때 마다 현재 페이지가 몇이냐에 따라서 offset이 정해질 것이고, 그 페이지에 맞는 게시물 목록 10개를 사용자에게 응답해준다.

 

다시 돌아와서 이제 리턴받은 게시물 5개와 사용자가 위치한 현재 페이지에 맞는 페이지네이션 필드 8개를 가지고 어떤식으로 페이지를 구성해서 jsp를 보여줄지도 필요하므로 이 2가지의 형태가 다른 데이터를 응답해주기위해 HashMap을 사용하였다.

 

 

이제 서버측으로 요청을 보내고 응답받은 데이터로 게시물목록을 출력하는 JavaScript 파일을 확인해보자

 

list.js

 

 

해당 메서드는 기존에 게시물 목록을 출력하기 위한 list() 메서드이다. 

일단 pno 변수가 location.href.split("=").pop()을 통해서 = 으로 구분되어 맨 마지막 에 있는 값을 반환받고있는데

지금 list 홈페이지에 어떤식으로 접근했길래 다음과 같은 메서드가 존재하는지 BoardController에 가서 확인해보자.

 

 

내가 사이드바 메뉴에서 게시물 목록 메뉴를 클릭했을 때, 다음과 같은 서버 포워딩 처리가 이루어진다.

게시물 목록 메뉴에는 a태그에 href 속성으로 다음과 같이 되어있다.

 

 그래서 위에 board/list/ 로 시작하는 어떠한 요청이 오더라도 일단 board/list.jsp를 포워딩해준다.

그리고 아까 보았듯이 게시물페이지 목록은 @RequestParam으로 처리할 예정이므로 ?기호와 page 파라미터에 값을 넣어주면서 요청을 보낸다. (일단 1페이지를 기본으로 보여주기 위해서 page를 고정값 1로 설정)

그래서 pno 변수에 식을 통해 맨 마지막에 page 파라미터에 값을 pno에 할당 받을 수 있다.

 

 

그리고 fetch 함수에 파라미터로 사용되는 url의 경우, 서버측 BoardApiController 클래스 내에 api/board/?page=3 과 같은 형식으로 요청을 받을 준비를 하고 있으므로 아까 추출한 pno 값을 ${} EL을 통해 url을 구성하였다.

 

fetch함수를 통해서 몇번 페이지 요청을 보냈는지 pno를 보내고 pno번째 페이지에 해당하는 출력 게시물 5개와 페이지네이션에 필요한 pageVo 객체를 resp로 리턴받는다. json 형식으로 온 데이터를 json()  메서드를 통해서 서버에서 반환할 때의

자료형인 map자료형으로 파싱해주고, 내가 채우려는 tb태그 내에 innerHTML을 통해서 게시물 5개를 

for of 문을 통해서 출력해주고 있다.

 

그리고 다른 페이지에 이동을 위해서 페이지네이션 버튼을 만들어주어야 한다 .

페이지네이션 버튼 구현

 

list.jsp에서 글 목록 아래에 버튼목록을 넣어줄 공간의 태그에 id로 page-area 값으로 지정하였다.

그 태그 안에다가 <button> 태그를 통해서 onclick으로 /board/list/?page=${}으로 설정하여 내가 원하는 페이지를 포워딩 해주도록 버튼을 만들 수 있다. 내가 설정한 버튼 개수는 5개이고, 보여지는 5개의 페이지 말고 이전과 이후 버튼을 통해서 또다른 앞뒤 10개의 페이지를 바로 포워딩 해줄수 있도록 이전 다음 버튼을 설정하였다.

 

만약 현재 4번 페이지에 있다면 1번부터 5번까지 페이지 버튼이 보여야하고, 이전페이지는 0번을 가르키고 있으므로 필요가 없어서 조건문을 설정해 두었다. 그리고 이후 페이지는 6번 페이지를 보여주면서 6 ~ 10번의 버튼을 보여주면 된다.

 

현재 페이지가 4번이라면 startPage는 1이들어가있고 endPage는 5이므로 1번부터 5번까지 페이지 버튼이 보일것이다.

 

맨 마지막에는 board/list/?page=4 와같은 페이지가 계속 포워딩 될때마다 바로바로 list() 메서드가 실행되면서 페이지가 보여져야 하므로 list() 메서드를 블록 밖에서 한번 적어주어 jsp 포워딩 마다 매번 실행되도록 한다.

 

페이지 결과는 다음과 같다.

 

 

 

이전버튼이 필요없는경우 이전 버튼이 보이지 않고,

 

이전 버튼과 다음버튼이 필요한 경우에는 출력되는 결과를 얻을 수 있다.