Stay Hungry Stay Foolish

PROJECT/[스프링 부트] 게시판

[스프링 부트] 9. 게시판 만들기 페이징 처리

dev스카이 2023. 10. 27. 15:53

페이징이란?

운영체제 관점에서, 컴퓨터가 메인 메모리에서 사용하기 위해 2차 기억 장치로부터 데이터를 저장하고 검색하는 메모리 관리 기법이다.

 

예를 들어, 100개의 게시물이 있으면 한 페이지에 100개를 모두 보여주는 것이 아닌 10개씩 나눠서 보여주는 것을 페이징 처리라고 한다. 

페이징 예시

 

01. 페이징 처리

JPA에서 제공하는 Pageable 인터페이스를 사용해서 페이징 처리를 한다.

01-1. BoardController의 boardList 메소드 수정

메소드 인자에 Pageable 인터페이스를 추가한다. Pageable 인터페이스가 많은데 그 중에 org.springframework.data.domain 인터페이스를 import 해준다. 

boardController의 boardList 메소드

 

• Pageable

  • 요청한 페이지를 반환한다.
  • JPA에서 제공해주는 객체이다.

 

※ Pag만 쳐도 관련 클래스과 인터페이스들이 검색된다. Tab으로 선택하면 된다.

 

boardController의 boardList 메소드

@PageableDefault

  • Pageable 객체 앞에 @PageableDefault 애노테이션을 붙이면 기본값을 설정할 수 있다.
  • PageableHandlerMethodArgumentResolverSupport 에 정의된 getDefaultFromAnnotationOrFallback() 메소드에서 확인할 수 있다.
  • @PageDefault로 어노테이션이 붙어 있는 경우에는 fallbackPageable이 아닌, @PageDefault어노테이션에 설정한대로 사용자에게 보내준다.
  • page : default 페이지(페이지 인덱스가 1이 아닌 0부터 시작)
  • size : 한 페이지에 나타낼 게시글 (여기서는 10개로 설정)
  • sort : 정렬 기준 컬럼 (여기서는 id값으로 정렬)
  • direction : 정렬 순서
    • DESC : 역순으로 정렬(내림차순이란 뜻으로 큰 값이 제일 먼저 오도록 즉, 최신 페이지가 상위에 오도록 처리)
    • ASC : DESC와 반대로 오름차순이라는 뜻이다. 디폴트 값이므로 생략이 가능하다.

 

인수로 받은 pageable을 boardList에 넘겨줄건데 현재 오류가 난다. 이는 서비스에서 처리를 해주지 않아서 생긴 문제이다. 오류를 해결하기 위해 Service에서 List 메소드를 수정한다.

 

Pageable에 대한 자세한 설명 ➜ https://tecoble.techcourse.co.kr/post/2021-08-15-pageable/

01-2. BoardService의 boardList 메소드 수정

boardService의 boardList 메소드

pageable 매개변수를 넣어주니 오류가 난다. List자리에 Page로 변경하면 오류가 사라진다.

boardService의 boardList 메소드

Controller도 다시 확인하면 오류가 사라진 것을 볼 수 있다.

boardController의 boardList 메소드

실행하기(http://localhost:8080/board/list)

좌 - 기존 리스트, 우 - 현재 리스트

기존에는 모든 게시글이 한 페이지에 다 보였지만, PageableDefault를 통해 페이징 처리한 결과 최신 글이 맨 위로 올라온 걸 볼 수 있고, 한 페이지에 10개의 게시글만 보이는 걸 알 수 있습니다.

 

현재는 0페이지(첫 번째 페이지)만 보이지만, url을 수정해 다른 페이지를 확인해 볼 수 있다. 0자리에 1을 넣으면 두 번째 페이지로 넘어간다.

좌 - 첫 번째 page, 우 - 두 번째 페이지

 

한 페이지에 보여줄 게시글의 수도 지정해 줄 수 있다. url에 size도 넘겨주는 것이다.

size = 20 즉, 첫 번째 게시물에 20개의 게시물을 보겠다는 말이다.

 

정리하면, 페이징 처리 시에 쿼리문 작성과 페이징 처리를 할 클래스도 생성해줘야 하는데 이때, jpa를 이용한다. jpa의 findAll 함수를 사용할 때 pageable 클래스를 넘겨주면 어려운 처리를 이렇게 간단하게 할 수 있다.

 

02. 페이지 블럭 출력

이제 프론트 즉, 리스트 페이지에 다음 페이지로 클릭으로 이동할 수 있게 보여준다.

 

02-1. boardlist.html에 thymeleaf 추가

<!DOCTYPE html>
<html lang="en" xmlns:th="http://thymeleaf.org">
                            .
                            .
<body>
  <div class="layout">
    <table border="1" align="center"> <!-- 리스트 중간 정렬 추가 -->
                        .
                        .
    </table>
    
     <!-- 페이징 블럭 처리 thymeleaf 추가 -->
     <nav style="text-align: center;"> <!-- 페이징 블럭도 중간 정렬 추가 -->
        <th:block th:each="page : ${#numbers.sequence(startPage, endPage)}">
            <a th:if="${page != nowPage}" th:href="@{/board/list(page = ${page - 1})}" th:text="${page}"></a>
            <strong th:if="${page == nowPage}" th:text="${page}" style="color : red"></strong>
        </th:block>
     </nav>

  </div>
</body></html>

• thymeleaf 문법

  • th:text - 태그 안에 데이터를 출력
    • Thymeleaf의 th:text 속성은 요소 의 텍스트 내용을 설정하는 데 사용된다.
    • 또한 이는 표준 HTML 텍스트 속성을 대체한다.
    • 따라서 제목, 단락, 레이블 등과 같은 텍스트 콘텐츠를 지원하는 모든 HTML 요소 내에 이를 넣을 수 있다.
    • 또한 이 속성을 사용하여 웹 페이지의 제목과 같은 동적 텍스트 콘텐츠를 표시할 수 있다.
  • th:each - 반복문, 반복 출력
    • th:each = "board : ${boardList}" - 기본 문법으로, 풀이하면 boardList의 값들을 board가 하나하나 참조한다.
  • "${number : #number(시작 번호, 끝번호)}" - 시작 번호에서 끝번호까지 반복

 

02-2. BoardController의 boardList 메소드 수정

1. "List"에 넘겨줄 페이지를 직접 넘겨주지 않고 따로 구현한다. 같은 코드를 다른 곳에도 사용해야 하기 때문에 객체를 따로 만들어서 불필요한 반복을 줄이고 재사용성을 높이기 위한 것이다. 

//추가
Page<Board> list = boardService.boardList(pageable);

 

2. 객체를 만들었으니 list를 담아준다. 기존에는 list 자리에 'boardService.boardList(pageable));'가 있었다.

  //수정
model.addAttribute("List", list);

 

3. 변수를 만든다.

int nowPage = list.getPageable().getPageNumber() + 1; //현재 페이지
int startPage = nowPage / pageable.getPageSize() * pageable.getPageSize() + 1; //블럭에서 보여줄 시작 페이지
int endPage = startPage + pageable.getPageSize() - 1; //블럭에서 보이는 마지막 페이지
  • nowPage
    • 현재 페이지를 의미하고, 현재 페이지를 넘겨준다.
    • nowPage에 pageable.getPageNumber()만 넘겨줘도 되지만 통일성을 위해 위와 같이 작성한다.
  • startPage
    • 블럭에서 보여줄 시작 페이지를 의미한다.
    • 현재페이지/페이징 개수*페이징 개수 + 1
  • endPage
    • 블럭에서 보이는 마지막 페이지를 의미한다.
    • 시작페이지 + 페이징 개수 - 1

 

4. 변수 설정이 끝났으면 값을 넘겨준다.

//추가
model.addAttribute("nowPage", nowPage);
model.addAttribute("startPage", startPage);
model.addAttribute("endPage", endPage);

 

실행하기(localhost:8080/board/list)

위와 같은 결과가 출력되는 것은 컨트롤러의 boardList에서 10개 단위로 나오도록 설정했기 때문이다.