[Spring] 예제 2 - 페이징 처리
테스트 코드 작성
아래 작성된 코드를 100번 이상 실행시킨다.

페이징 처리의 필요성

현재 게시글 데이터가 160여개가 추가되었는데 이 많은 양의 데이터를 한 페이지에 담기에는 사용자 입장에서 이용이 불편할 것이다.
→ 한 페이지에 있는 데이터의 양이 너무 많다.

✍ mainPage.jsp
ul 태그에 mb-0 작성 (글쓰기 버튼 크기 커지지 않게 하기 위해)
mx-auto : 양 옆의 margin을 가운데로
< 이전 특수문자
> 이후 특수문자
<div class="row"><!-- 버튼 -->
<div class="col-6">
<nav aria-label="Page navigation example">
<ul class="pagination">
<li class="page-item"><a class="page-link" href="#">Previous</a></li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">4</a></li>
<li class="page-item"><a class="page-link" href="#">5</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</nav>
</div>
<div class="col-2 ms-auto d-grid">
<c:if test="${!empty sessionUser }">
<a href="./writeContentPage" class="btn btn-primary">글쓰기</a>
</c:if>
</div>
</div>
</div>

ROWNUM: 출력하는 순서대로 일련번호를 붙여주는 것
ORDER BY가 먼저 적용되는 것이 아니라 출력이 먼저된다.
ORDER BY가 나중에 수행된다.
→ ORDER BY를 먼저 수행하고 ROWNUM을 붙여야 한다. →순서를 바꿀 때 서브쿼리 사용


ROWNUM: 출력하고 나서 수행된다
동작순서 주의할 것



((1-1)*10)+1
첫 1: 페이지번호

10개씩 보기 페이징 쿼리

ORDER BY를 먼저 한 다음에 ROWNUM을 붙여야함.
✍ mainPage.jsp
<div class="col-6 mx-auto">
<nav aria-label="Page navigation example">
<ul class="pagination mb-0">
<li class="page-item"><a class="page-link" href="#"><</a></li>
<li class="page-item"><a class="page-link" href="./mainPage?page=1">1</a></li>
<li class="page-item"><a class="page-link" href="./mainPage?page=2">2</a></li>
<li class="page-item"><a class="page-link" href="./mainPage?page=3">3</a></li>
<li class="page-item"><a class="page-link" href="./mainPage?page=4">4</a></li>
<li class="page-item"><a class="page-link" href="./mainPage?page=5">5</a></li>
<li class="page-item"><a class="page-link" href="#">></a></li>
</ul>
</nav>
</div>
쿼리
SELECT COUNT(*) FROM fp_board;
✍ BoardSqlMapper
selectAll 메서드 수정
public List<BoardDto> selectAll(int pageNum);
// 글 개수 가져오는 것
public int getBoardCount();
<= 는 xml에서 특수문자로 인식
<![CDATA[]]>
크고 작음을 비교하는 쿼리를 작성할때 사용
<select id="selectAll" resultType="com.ja.finalproject.dto.BoardDto">
<![CDATA[
SELECT t2.* FROM (
SELECT t1.*, ROWNUM rnum FROM(
SELECT fb.* FROM fp_board fb
ORDER BY id DESC
) t1
) t2
WHERE t2.rnum >= ((#{pageNum}-1)*10)+1 AND t2.rnum <= #{pageNum}*10
]]>
</select>
<select id="getBoardCount" resultType="int">
SELECT COUNT(*) FROM fp_board
</select>
✍ BoardServiceImpl
메서드 수정
public List<Map<String, Object>> getBoardList(int pageNum) {
// List는 object를 주로 담진 않는다. 일률적으로 담는다.
List<Map<String, Object>> list = new ArrayList<>();
List<BoardDto> boardDtoList = boardSqlMapper.selectAll(pageNum);
for(BoardDto boardDto : boardDtoList) {
// 한 바퀴 돌때마다 map이 생성되어야 한다. map은 키가 중복되면 안된다.
Map<String, Object> map = new HashMap<>();
int memberId = boardDto.getMember_id();
System.out.println(memberId);
MemberDto memberDto = memberSqlMapper.selectById(memberId);
System.out.println(memberDto);
map.put("memberDto", memberDto);
map.put("boardDto", boardDto);
list.add(map);
}
return list;
}
✍BoardController
@RequestMapping("mainPage")
public String mainPage(Model model, int page) {
List<Map<String, Object>> list = boardService.getBoardList(page);
model.addAttribute("list", list); //request 객체에 담는다고 생각.
return "board/mainPage";
}
서버 가동
(중요)
@RequestParam
@RequestParam(value = "aaa") int page
외부에서 aaa라고 보내면 서버에서 page로 인식
defaultValue
만약에 파라미터가 날라오지 않으면 null로 인식할텐데 파라미터가 날라오지 않은 경우 page라는 변수에 1을 설정하겠다는 뜻
@RequestMapping("mainPage")
public String mainPage(Model model, @RequestParam(value = "page", defaultValue = "1" ) int page) {
List<Map<String, Object>> list = boardService.getBoardList(page);
model.addAttribute("list", list); //request 객체에 담는다고 생각.
return "board/mainPage";
}
BoardServiceImpl
public int getBoardCount() {
return boardSqlMapper.getBoardCount();
}
BoardController
@RequestMapping("mainPage")
public String mainPage(Model model, @RequestParam(value = "page", defaultValue = "1") int page) {
List<Map<String, Object>> list = boardService.getBoardList(page);
int boardCount = boardService.getBoardCount();
int totalPage = (int)Math.ceil(boardCount / 10.0);
model.addAttribute("list", list); //request 객체에 담는다고 생각.
model.addAttribute("totalPage", totalPage);
return "board/mainPage";
}
mainPage.jsp
<div class="col-6 mx-auto">
<nav aria-label="Page navigation example">
<ul class="pagination mb-0">
<li class="page-item"><a class="page-link" href="#"><</a></li>
<c:forEach begin="1" end="${totalPage}" var="index">
<li class="page-item"><a class="page-link" href="./mainPage?page=${index}">${index}</a></li>
</c:forEach>
<li class="page-item"><a class="page-link" href="#">></a></li>
</ul>
</nav>
</div>

BoardController
@RequestMapping("mainPage")
public String mainPage(Model model, @RequestParam(value = "page", defaultValue = "1") int page) {
List<Map<String, Object>> list = boardService.getBoardList(page);
int boardCount = boardService.getBoardCount();
int totalPage = (int)Math.ceil(boardCount / 10.0);
model.addAttribute("list", list); //request 객체에 담는다고 생각.
model.addAttribute("totalPage", totalPage);
model.addAttribute("currentPageNum", page);
return "board/mainPage";
}
mainPage.jsp
<div class="col-6 mx-auto">
<nav aria-label="Page navigation example">
<ul class="pagination mb-0">
<li class="page-item"><a class="page-link" href="#"><</a></li>
<c:forEach begin="1" end="${totalPage}" var="index">
<c:choose>
<c:when test="${index == currentPage}">
<li class="page-item active"><a class="page-link" href="./mainPage?page=${index}">${index}</a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="./mainPage?page=${index}">${index}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<li class="page-item"><a class="page-link" href="#">></a></li>
</ul>
</nav>
</div>

BoardController
@RequestMapping("mainPage")
public String mainPage(Model model, @RequestParam(value = "page", defaultValue = "1") int page) {
List<Map<String, Object>> list = boardService.getBoardList(page);
int boardCount = boardService.getBoardCount();
int totalPage = (int)Math.ceil(boardCount / 10.0);
// 1 2 3 4 5 6 7 8 9 10
int startPage = ((page - 1) / 5) * 5 + 1;
int endPage = ((page - 1) / 5+1) * 5;
model.addAttribute("list", list); //request 객체에 담는다고 생각.
model.addAttribute("totalPage", totalPage);
model.addAttribute("currentPage", page);
return "board/mainPage";
}
보통 페이지 처리할때는 object를 만드는 편이다.
@RequestMapping("mainPage")
public String mainPage(Model model, @RequestParam(value = "page", defaultValue = "1") int page) {
List<Map<String, Object>> list = boardService.getBoardList(page);
int boardCount = boardService.getBoardCount();
int totalPage = (int)Math.ceil(boardCount / 10.0);
// 1 2 3 4 5 6 7 8 9 10
int startPage = ((page - 1) / 5) * 5 + 1;
int endPage = ((page - 1) / 5+1) * 5;
// endPage가 totalPage
if (endPage > totalPage) {
endPage = totalPage;
}
model.addAttribute("list", list); //request 객체에 담는다고 생각.
model.addAttribute("totalPage", totalPage);
model.addAttribute("currentPage", page);
model.addAttribute("startPage", startPage);
model.addAttribute("endPage", endPage);
return "board/mainPage";
}

<div class="col-6 mx-auto">
<nav aria-label="Page navigation example">
<ul class="pagination mb-0">
<li class="page-item"><a class="page-link" href="./mainPage?page=${startPage -1}"><</a></li>
<c:forEach begin="${startPage}" end="${endPage}" var="index">
<c:choose>
<c:when test="${index == currentPage}">
<li class="page-item active"><a class="page-link" href="./mainPage?page=${index}">${index}</a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="./mainPage?page=${index}">${index}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<li class="page-item"><a class="page-link" href="${endPage + 1}">></a></li>
</ul>
</nav>
</div>
<div class="row"><!-- 버튼 -->
<div class="col-6 mx-auto">
<nav aria-label="Page navigation example">
<ul class="pagination mb-0">
<c:choose>
<c:when test="${startPage <= 1}">
<li class="page-item disabled"><a class="page-link" href="./mainPage?page=${startPage-1}"><</a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="./mainPage?page=${startPage-1}"><</a></li>
</c:otherwise>
</c:choose>
<!-- 페이지 번호 -->
<c:forEach begin="${startPage }" end="${endPage }" var="index">
<c:choose>
<c:when test="${index == currentPage}">
<li class="page-item active"><a class="page-link" href="./mainPage?page=${index }">${index }</a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="./mainPage?page=${index }">${index }</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
<c:choose>
<c:when test="${endPage >= totalPage}">
<li class="page-item disabled"><a class="page-link" href="./mainPage?page=${endPage+1}">></a></li>
</c:when>
<c:otherwise>
<li class="page-item"><a class="page-link" href="./mainPage?page=${endPage+1}">></a></li>
</c:otherwise>
</c:choose>
</ul>
</nav>
</div>