스프링 부트 게시판 페이징 - seupeuling buteu gesipan peijing

점프 투 스프링부트 0장 들어가기 전에 0-01 머리말 0-02 저자소개 0-03 주요변경이력 0-04 이 책을 읽기 전에 1장 스프링부트 개발 준비! 1-01 필자가 생각하는 스프링부트란? 1-02 자바 설치하기 1-03 스프링부트 개발 환경 준비하기 1-04 스프링부트 맛보기 1-05 스프링부트 도구 설치하기 2장 스프링부트의 기본 요소 익히기! 2-01 스프링부트 프로젝트의 구조 2-02 컨트롤러 2-03 JPA 2-04 엔티티 2-05 리포지터리 2-06 도메인 별로 분류하기 2-07 질문 목록과 템플릿 2-08 ROOT URL 2-09 서비스 2-10 질문 상세 2-11 답변 등록 2-12 스태틱 디렉터리와 스타일시트 2-13 부트스트랩 2-14 템플릿 상속 2-15 질문 등록과 폼 2-16 공통 템플릿 3장 SBB 서비스 개발! 3-01 내비게이션바 3-02 페이징 3-03 게시물에 일련번호 추가하기 3-04 답변 개수 표시 3-05 스프링 시큐리티 3-06 회원가입 3-07 로그인과 로그아웃 3-08 엔티티 변경 3-09 글쓴이 표시 3-10 수정과 삭제 3-11 추천 3-12 앵커 3-13 마크다운 3-14 검색 3-15 SBB 추가 기능 4장 세상에 선보이는 SBB 서비스! 4-01 서버 4-02 AWS 라이트세일 4-03 서버 접속 설정 4-04 서버 접속 프로그램 4-05 SBB 오픈 4-06 서버 스크립트 4-07 개발과 서버 환경 분리 4-08 Nginx 4-09 로깅 4-10 도메인 4-11 SSL 4-12 PostgreSQL A. 부록 A-01 인텔리제이 사용하기 A-02 AWS 라이트세일 사용 취소 A-03 댓글 (삭제예정) B. 마치며

페이징 - 백엔드 개념 부분


페이징이란?

  • 페이징이란 여러 게시물을 볼 때 일정 갯수 이상이 넘어가면 다음 페이지에 존재할 수 있게 하는 것을 의미합니다.
    스프링 부트 게시판 페이징 - seupeuling buteu gesipan peijing
  • 위와 같이 게시글이 일정 갯수가 넘어가면 다음 페이지에 이전 게시물들이 있는 형태를 ui 페이징이라고 합니다.

Pageable 인터페이스를 사용한 컨트롤러

    @GetMapping("/board/list")
    public String boardList(Model model, @PageableDefault(page=0, size=10, sort="id", direction=Sort.Direction.DESC) Pageable pageable){
        //서비스에서 생성한 리스트를 list라는 이름으로 반환하겠다.
        model.addAttribute("list", boardService.boardList(pageable));
        return "boardlist";
    }
  • Pageable 인터페이스를 통해서 해당 사이트의 페이징 정보를 설정할 수 있다
  • page = 현재 페이지, 인덱스 0부터 시작
    size = 한 페이지 당 허용되는 데이터 갯수
    sort = 정렬하는 조건
    direction = 내림차순, 오름차순
  • pageable을 매개변수로 설정한 후 위와 같이 요청이 오면 JpaRepository는 그에 해당하는 pageable 객체를 자동으로 만들어준다.

JPA를 사용한 페이징

  • jpa를 사용해서 페이징을 구현할 때 localhost:8080/board/list?page=1&size=10으로 나오면 page = 1(원래는 index 0부터 시작) size = 10개일때까지 1페이지로 넣고 size가 넘어가면 다음 페이지로 옮겨줍니다.
  • 이때 우리는 페이징 처리와 함께 게시물 정렬 순서 역시 정리해줄 것입니다.
  • pageable을 매개변수로 설정한 후 위와 같이 요청이 오면 JpaRepository는 그에 해당하는 pageable 객체를 자동으로 만들어준다.

서비스 수정

    public Page<Board> boardList(Pageable pageable){
        //기존 List<Board>값으로 넘어가지만 페이징 설정을 해주면 Page<Board>로 넘어갑니다.
        return boardRepository.findAll(pageable);
    }

페이지 블럭 출력을 위한 컨트롤러 설정

[페이지 블럭을 뷰로 넘겨주기 위한 컨트롤러 코드 작성]

    @GetMapping("/board/list")
    public String boardList(Model model, @PageableDefault(page=0, size=10, sort="id", direction=Sort.Direction.DESC) Pageable pageable){


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


        //페이지블럭 처리
        //1을 더해주는 이유는 pageable은 0부터라 1을 처리하려면 1을 더해서 시작해주어야 한다.
        int nowPage = list.getPageable().getPageNumber() + 1;
        //-1값이 들어가는 것을 막기 위해서 max값으로 두 개의 값을 넣고 더 큰 값을 넣어주게 된다.
        int startPage =  Math.max(nowPage - 4, 1);
        int endPage = Math.min(nowPage+9, list.getTotalPages());


        model.addAttribute("list", list);
        model.addAttribute("nowPage",nowPage);
        model.addAttribute("startPage", startPage);
        model.addAttribute("endPage", endPage);



        return "boardlist";
    }
  • 해당 list 출력부와 페이지부를 나눠서 데이터를 뷰로 넘겨줍니다.
  • int nowPage = list.getPageable().getPageNumber() + 1; - 현재 페이지를 나타내는 변수로 index가 0부터 시작하기 때문에 +1을 해줍니다.
  • int startPage = Math.max(nowPage - 4, 1); - 현재 페이지에서 가장 앞에 페이지 번호를 보여줄 변수입니다.(이때 max 함수를 사용하는 이유는 현재 페이지에서 -4를 해줬을 때 1보다 작은 수가 나오면 안되기 때문에 1 혹은 현재페이지 - 4 했을 때 더 큰 값을 쓰기 위함입니다.)
  • int endPage = Math.min(nowPage+ + 9, list.getTotalPages()); - 현재 페이지에서 가장 뒤에 페이지 번호를 보여줄 변수입니다. (이때 min 함수를 사용하는 이유는 해당 번호가 넘어가버리면 안 되기 때문입니다. 페이지가 11페이지까지 있을 때 현재 페이지가 3페이지라면 12페이지까지 보이기 때문에 이러면 안 되어서 최소값을 구하는 방식으로 진행했습니다.)

뷰 페이지

뷰 페이지 작성 코드

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>게시글 리스트 페이지</title>
</head>

<style>
    .layout {
        width: 500px;
        margin: 0 auto;
        margin-top: 40px;
    }
</style>
<body>

    <div class="layout">
        <table>
            <thead>
                <tr>
                    <th>글번호</th>
                    <th>제목</th>
                </tr>
            </thead>
            <tbody>
                <tr th:each = "board:${list}">
                    <td th:text="${board.id}">1</td>
                    <td >
                        <a th:text="${board.title}" th:href="@{/board/view(id=${board.id})}"></a>
                    </td>
                </tr>
            </tbody>
        </table>

        <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>
    </div>

</body>
</html>
  • <th:block th:each="page:${#numbers.sequence(startPage,endPage)}"> - th: block은 마땅히 쓸 테그가 없을 때 사용합니다. 또한 startPage부터 endPage를 a테그로 출력하고 현재 페이지는 strong - 강조 테그를 사용해서 따로 링크 처리 없이 보여줍니다.

  • <a th:if="${page != nowPage}" th:href="@{/board/list(page=${page-1})}"th:text ="${page}"></a> - 현재 페이지가 아닌 경우엔 a테그로 이동할 수 있게 합니다. 이때 localhost:8080/board/list?page=1부터 쿼리 스트링으로 시작합니다.

  • <strong th:if="${page==nowPage}" th:text ="${page}" style="color:red"></strong> - 현재 페이지라면 빨간색으로 강조표시를 해 따로 링크는 걸지 않고 현재 페이지임을 나타내 줍니다.

게시물 목록 페이징 현황

스프링 부트 게시판 페이징 - seupeuling buteu gesipan peijing


오류 해결

java.sql.SQLSyntaxErrorException: (conn=601) Unknown column 'board0_.filename' in 'field list'

  • 이 오류는 앞선 포스팅에서 파일 업로드 작업 중에 필드를 java entity class에만 추가를 해줘서 생긴 문제였다. 본래는 " " 쌍따옴표를 쓰지 않고 ' '를 사용해서 문자열로 인식하지 못한 문제거나 필드 추가를 DB에 안 해서 생기는 문제인데 내 경우엔 후자였다.
  • 본인은 현재 프로젝트에 maria DB를 사용해서 간편하게 테이블을 보고 컬럼들을 확인했고 이 문제를 해결할 수 있었다.