나의 수업일지

인천 일보 아카데미 53일차 -비로그인 게시판- List 페이징 기능

GUPING 2023. 5. 9. 01:57
  • Paging 기능 만들어보기

사진과 같이 한페이지에 9개의 게시글이 출력되고,

하단의 페이지번호는 1~3 ,4~6 이런식으로 3개씩 끊어서 출력했습니다

1아래는 더 이상 [이전] 으로 돌아갈 수 없기 때문에 회색으로 돌아갈 수 있는 페이지가 있다면

다시 검은색으로 활성화 됩니다 [다음] 부분도 마찬가지로 마지막 페이지에서는 비활성화 됩니다

 

 

  • Paging.jsp
<h2 style="text-align: center">boardPagingList</h2>
        <table class="table table-striped table-hover text-center">
            <thead>
            <tr>
                <th>글번호</th>
                <th>제목</th>
                <th>작성자</th>
                <th>작성시간</th>
                <th>조회수</th>
            </tr>
            <c:forEach items="${boardList}" var="board">
                <tr>
                    <td style="border: 1px solid black;text-align: center;padding: 5px">
                        <a href="/board?id=${board.id}&page=${paging.page}"
                           style="text-decoration: none;color: black">${board.id}</a>
                    </td>
                    <td style="border: 1px solid black;text-align: center;padding: 5px">
                        <a href="/board?id=${board.id}&page=${paging.page}"
                           style="text-decoration: none;color: black">${board.boardTitle}</a>
                    </td>
                    <td style="border: 1px solid black;text-align: center;padding: 5px">
                        <a href="/board?id=${board.id}&page=${paging.page}"
                           style="text-decoration: none;color: black">${board.boardWriter}</a>
                    </td>
                    <td style="border: 1px solid black;text-align: center;padding: 5px">
                        <a href="/board?id=${board.id}&page=${paging.page}"
                           style="text-decoration: none;color: black"><fmt:formatDate value="${board.boardCreateDate}"
                                                                                      pattern="yyyy-MM-dd HH:mm"></fmt:formatDate></a>
                    </td>
                    <td style="border: 1px solid black;text-align: center;padding: 5px">
                        <a href="/board?id=${board.id}&page=${paging.page}"
                           style="text-decoration: none;color: black">${board.boardHits}</a>
                    </td>
                </tr>
            </c:forEach>
            </thead>
            여기까지는 게시글을 롬북의 C태그를 사용해 게시글을 출력했습니다
            잘 모르겠다면 List 게시글을 참고해주세요
            
            <tbody>
            <tr>
                <th colspan="5" style="padding: 5px"><c:choose>
                    <c:when test="${paging.page<=1}">
                        <a style="text-decoration: none;color: grey">[이전]</a>
                    </c:when>
                    	현재 페이지가 1페이지면 [이전] 글자만 보여줌 기능 off
                    
                    <c:otherwise>
                        <a href="/board/paging?page=${paging.page-1}"
                           style="text-decoration: none;color: black">[이전]</a>
                    </c:otherwise>
                    	1페이지가 아닌 경우에는 [이전]을 클릭하면 현재 페이지보다 1 작은 페이지 요청
                        Controller에 현재 페이지 -1를 호출하여 구현
                </c:choose>
                
                    <c:forEach begin="${paging.startPage}" end="${paging.endPage}" var="i" step="1">
                    새로운 형태의 C태그 for문 사용 자바를 처음배울때 배운 for문이라고 생각하면 편하다
                    	for(int i=startPage; i<=endPage; i++) 이런 형식이다
                    
                        <c:choose>
                            요청한 페이지에 있는 경우 현재 페이지 번호는 텍스트만 보이게
                            <c:when test="${i eq paging.page}">
                            여기서 'eq' 는 '==' 를 뜻한다 (같으면)
                                <a class="page-link" style="text-decoration: none;color: violet">${i}</a>
                                요청페이지와 현재 페이지번호가 같다면 기능off
                            </c:when>
                            <c:otherwise>
                                <a class="page-link" href="/board/paging?page=${i}"
                                   style="text-decoration: none;color: black">${i}</a>
                                요청페이지와 현재 페이지 번호가 다르다면
                                언제든지 이동가능하도록 링크를 활성화하도록 구현
                            </c:otherwise>
                        </c:choose>
                    </c:forEach>
                    
                    <c:choose>
                        <c:when test="${paging.page>=paging.maxPage}">
                            <a class="page-link" style="text-decoration: none;color: grey">[다음]</a>
                            현재 페이지가 마지막페이지이면 [다음] 글자만 보여줌 기능 off
                        </c:when>
                        <c:otherwise>
                            <a class="page-link" href="/board/paging?page=${paging.page+1}"
                               style="text-decoration: none;color: black">[다음]</a>
                               현재 페이지가 마지막이 아니면
                               Controller에 현재페이지 +1을 호출하도록 기능 구현
                        </c:otherwise>
                    </c:choose></th>
            </tr>
            </tbody>
        </table>

 

 

  • Controller
    @GetMapping("/paging")
    public String paging(@RequestParam(value = "page", required = false, defaultValue = "1" ) int page,Model model){
    선텍적 파라미터 사용 @RequstParam을 사용해 page라는 파라미터 요청을 매핑합니다
    required를 통해 해당 파라미터가 필수인지 여부를 체크합니다 false라면 필수는 아닙니다
    defaulValue를 통해 파라미터로 받은 값이 서버에 없는 값이라면 자동으로 기본값 1이 지정됩니다
    
        List<BoardDTO> boardDTOList = boardService.pagingList(page);
        사용자가 요청한 페이지에 해당하는 글 목록 데이터

        PageDTO pageDTO = boardService.pagingParam(page);
        하단에 보여줄 페이지 번호 목록데이터
        
        model.addAttribute("boardList",boardDTOList);
        model.addAttribute("paging",pageDTO);
        이렇게 따로 model에 담아 페이지로 함께 이동한다
        return "boardPages/boardPaging";
    }

 

 

  • Service
    public List<BoardDTO> pagingList(int page) {
    사용자가 요청한 페이지에 해당하는 글 목록 데이터
    
    	int pageStart = (page-1) * pageLimit;
        한페이지에서 시작할 글의 시작점
    
        int pageLimit = 9;
        시작점부터 한페이지에 보여줄 글의 갯수
        
        이렇게 PAGE가 1이면 0부터 9개의 글 PAGE가 2면 9부터 9개의 글을 출력
        
        Map<String,Integer> pagingParams = new HashMap<>();
        DB에서 쿼리문의 파라미터 값으로 활용하기 위해 Map담아 한번에 넘겨줍니다
        
        pagingParams.put("start", pageStart);
        pagingParams.put("limit",pageLimit);
        key값은 start , limit으로 설정했습니다
        
        List<BoardDTO> boardDTOList = boardRepository.pagingList(pagingParams);
        Repository에서는 DB에 저장후 설정한 수량의 List를 출력해 받아옵니다
        
        return boardDTOList;
        이후 리턴
    }

    public PageDTO pagingParam(int page) {
    하단에 보여줄 페이지 번호 목록데이터
    
        int pageLimit = 9;
        현페이지에 보여줄 글 갯수
        
        int blockLimit = 3;
        하단에 보여줄 페이지 번호 갯수
        
        int boardCount = boardRepository.boardCount();
        전체 글 갯수 조회 Repsitory를통해 DB에서 가져옴
        
        int maxPage = (int)(Math.ceil((double)boardCount / pageLimit));
        전체 페이지 갯수 계산 가져온 값은 정수이기 때문에 변환을 하지 않으면 소수점은 배제당함
        double로 형변환을 후 Math.ceil을 통해 올림 이후 다시 int로 형변환
        
        int startPage = (((int)(Math.ceil((double) page / blockLimit))) - 1) * blockLimit + 1;
        시작 페이지 값 계산(1,4,7,10~~)
        하단의 페이지의 시작점 1에서 3페이지까지 보여주고 다음은 4페이지가 나오는
        이 너무나도 당연한걸 설정해야함
        
        int endPage = startPage + blockLimit - 1 ;
        마지막 페이지 값 계산(3.6.9.12~~)
        마지막 페이지가 3.6.9등 시작 페이지값과 맞지 않을 수 있기 때문에
        마지막 페이지값도 설정해주어야함
        
        if(endPage > maxPage){
            endPage = maxPage;
        }
        전체 페이지 갯수가 계산한 endPage 보다 작을 대는 endPage 값을 maxPage와 같게 세팅
        그래도 빠지는 값은 endPage가 maxPage보다 크다면 if문을 통해 같아지게 설정함
        
        PageDTO pageDTO = new PageDTO();
        pageDTO.setPage(page);
        pageDTO.setMaxPage(maxPage);
        pageDTO.setStartPage(startPage);
        pageDTO.setEndPage(endPage);
        위에서 세팅한 값을 모두 pageDTO객체에 저장해준 후
        
        return pageDTO;
        리턴하며 마무리
    }

 

 

  • Repository
    public List<BoardDTO> pagingList(Map<String, Integer> pagingParams) {
        return sql.selectList("Board.paging",pagingParams);
    }
    Repository에서 설정한 파라미터값을 담은 Map을 사용해
    파라미터 값만큼의 List를 DB에서 뽑아오기 위한 메소드

    public int boardCount() {
        return sql.selectOne("Board.count");
    }
    Repository의 pagingParam에 전체글갯수를 전달해주기 위한 메소드

 

 

  • Mapper
    <select id="paging" parameterType="java.util.HashMap" resultType="board">
        select * from board_table order by id asc limit #{start},#{limit}
    </select>
    Map으로 받아온 파라미터 값을 limit에서 사용하여 List를 끊어서 출력함
    
    <select id="count" resultType="Integer">
        select count(id) from board_table
    </select>
    말그대로 총게시글이 몇개인지 카운트만하는 쿼리문