[SpringBoot] 게시판 목록 < paging | pagination > 처리 및 검색기능 구현 코드

 


나의 첫 포스팅 😮‍💨

프젝하다가 페이징 처리 해야하는데

복습 안했더니 기억안나서 

 부랴부랴 되짚어보는 페이징 부분 정리 !


 

우선 컨트롤러를 작성하기 전에 페이징에 필요한 정보를 정리해보자.

  페이징(Paging)|페지네이션(Pagination)
- [c]페이지 당 표시할 게시글의 수(경우에 따라 다르지만 클라이언트에게 맡기는 경우가 대부분이지만 우린 상수로 빼놓을것) : 10
- [P]요청한 페이지 번호 > Assert >=1
- [t]전체 게시글의 개수 > DB
- [n]이동 가능한 최소 페이지(<<) : 1
- [x] 이동 가능한 최대 페이지(>>): t%c !=0 ? (t/c)+1 :t/c || (t-1)/c+1 > 후자가 성능상 유리함
- [s] 표시 시작 페이지: p/10 == 0 ? 1 : 10 * (p/10)+1 || ((p-1)/10)*10+1 > 후자가 성능상 유리함
- [e] 표시 끝 페이지:  Math.min(s+9,x) || s+9 >x ? x: (s+9) >> 항상! 이동가능한 페이지 이하이기때문. 13을 요청했을때 생각해보자
 = LIMIT n OFFSET (p-1)*n

<Controller> 

 @RequestMapping(value = "list",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    @ResponseBody
    public ModelAndView getList(@RequestParam(value = "bid") String bid, //boardId
                                @RequestParam(value = "page", required = false,
                                        defaultValue = "1") Integer page,
                                @RequestParam(value = "criterion", required = false) String criterion, // 검색기준
                                @RequestParam(value = "keyword", required = false) String keyword)//검색어 {


        page = Math.max(1, page);
        ModelAndView modelAndView = new ModelAndView("bbs/list");
        BoardEntity board = this.bbsService.getBoard(bid);
        modelAndView.addObject("board", board);

            int totalCount; //pagination 하려고 가져온 것
            if ( board != null) {
                totalCount = this.bbsService.getArticleCount(board, criterion, keyword);
                PagingModel paging = new PagingModel(totalCount, page);
                modelAndView.addObject("paging", paging);

                ArticleReadVo[] articles = this.bbsService.getArticles(board, paging,criterion,keyword);
                modelAndView.addObject("articles", articles);
            }

        return modelAndView;
    }

<Service>

// 게시물을 가져오는 서비스
public ArticleReadVo[] getArticles(BoardEntity board, PagingModel paging,String criterion,String keyword) {
        // 매개변수로 갖는 게시판의 종류,검색기준, 검색어, 페이지당 표시할 게시글의 개수 , 
        return this.bbsMapper.selectArticlesByBoardId(
                board.getId(), //게시판의 종류
                criterion, // 검색기준
                keyword, // 검색어
                paging.countPerPage, // 페이지당 표시할 게시글의 개수
                (paging.requestPage-1)*paging.countPerPage); 
                //(요청한 페이지 번호-1)*페이지당 표시할 게시글의 개수 
                
    }
//검색 서비스
    public int getArticleCount (BoardEntity board, String criterion, String keyword) {

        return this.bbsMapper.selectArticleCountByBoardId(board.getId(),criterion,keyword);
    }

<IMapper>

ArticleReadVo[] selectArticlesByBoardId(@Param(value = "boardId") String boardId,
                                        @Param(value = "criterion") String criterion,
                                        @Param(value = "keyword") String keyword,
                                        @Param(value = "limit") int limit,
                                        @Param(value = "offset") int offset);
int selectArticleCountByBoardId(@Param(value = "boardId") String boardId,
                                @Param(value = "criterion") String criterion,
                                @Param(value = "keyword") String keyword);

<Mapper>

<select id="selectArticlesByBoardId"
        resultType="dev.yhpark.studymemberbbs.vos.bbs.ArticleReadVo">
    SELECT `article`.`index` AS `index`,
    `article`.`user_email` AS `userEmail`,
    `article`.`board_id` AS `boardId`,
    `article`.`title` AS `title`,
    `article`.`view` AS `view`,
    `article`.`written_on` AS `writtenOn`,
    `article`.`modified_on` AS `modifiedOn`,
    COUNT(`comment`.`index`) AS `commentCount`,
    `user`.`nickname` AS `userNickName`

    FROM `study_bbs`.`articles` AS `article`
    LEFT JOIN `study_member`.`users` AS `user` ON `article`.`user_email` = `user`.`email`
    LEFT JOIN `study_bbs`.`comments` AS `comment` ON `comment`.`article_index` = `article`.`index`

    WHERE BINARY `article`.`board_id` = #{boardId}

    <if test="criterion != null and criterion.equals('title')">
        AND REPLACE(`article`.`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
    </if>
    <if test="criterion !=null and criterion.equals('all')">
        AND (REPLACE(`article`.`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
        OR REPLACE(`article`.`content`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%'))
    </if>
    <if test="criterion !=null and criterion.equals('nickName')">
        AND BINARY `user`.`nickname` = #{keyword}
    </if>
    GROUP BY `article`.`index`
    ORDER BY `article`.`index` DESC
    LIMIT #{limit} OFFSET #{offset};
</select>
<select id="selectArticleCountByBoardId"
        resultType="int">
    SELECT COUNT(0)
    FROM `study_bbs`.`articles` AS `article`

    <if test="criterion !=null and criterion.equals('nickName')">
        LEFT JOIN `study_member`.`users` AS `user` ON `article`.`user_email` = `user`.`email`
    </if>
    WHERE `board_id` = #{boardId}
    <if test="criterion != null and criterion.equals('title')">
        AND REPLACE(`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
    </if>
    <if test="criterion !=null and criterion.equals('all')">
        AND (REPLACE(`title`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%')
        OR REPLACE(`content`, ' ', '') LIKE CONCAT('%', REPLACE(#{keyword}, ' ', ''), '%'))
    </if>
    <if test="criterion !=null and criterion.equals('nickName')">
        AND BINARY `user`.`nickname` = #{keyword}
    </if>

</select>

<HTML>

<div class="page-container"
     th:with="urlBuilder = ${T(org.springframework.web.servlet.support.
ServletUriComponentsBuilder).fromCurrentRequest()}">
    <a th:if="${paging.requestPage > 1}"
       th:href="@{${urlBuilder.replaceQueryParam('page',paging.minPage).build().toUriString()}}"
       class="page">
        <i class="fa-solid fa-angles-left"></i>
    </a>
    <a th:if="${paging.requestPage > 1}"
       th:href="@{${urlBuilder.replaceQueryParam('page',(paging.requestPage)-1).build().toUriString()}}"
       class="page">
        <i class="fa-solid fa-angle-left"></i>
    </a>
    <a class="page"
       th:each="page:${#numbers.sequence(paging.startPage,paging.endPage)}"
       th:class="${'page '+(page == paging.requestPage?'selected':'')}"
       th:text="${page}"
       th:href="@{${urlBuilder.replaceQueryParam('page',page).build().toUriString()}}"></a>

    <a href="#" class="page"
       th:if="${paging.requestPage < paging.maxPage}"
       th:href="@{${urlBuilder.replaceQueryParam('page',(paging.requestPage)+1).build().toUriString()}}">
        <i class="fa-solid fa-angle-right"></i>
    </a>
    <a th:if="${paging.requestPage < paging.maxPage}"
       th:href="@{${urlBuilder.replaceQueryParam('page',paging.maxPage).build().toUriString()}}"
       class="page">
        <i class="fa-solid fa-angles-right"></i>
    </a>
</div>