본문 바로가기
Spring/게시판프로젝트

[Spring] 게시판 프로젝트14 - 페이징 처리2

by 태옹 2021. 7. 20.

페이징 처리1 게시물과 이어지는 내용입니다.
2021.07.20 - [Spring/게시판프로젝트] - [Spring] 게시판 프로젝트13 - 페이징 처리1

 

[Spring] 게시판 프로젝트13 - 페이징 처리1

프로젝트용으로 데이터가 그렇게 많지 않기 때문에 페이징 처리에 고려하지 않을 수도 있지만 실 서비스에서는 대량의 데이터 조회를 위해 페이징 처리가 필수적이다. 이번 실습에서는 게시판

taetoungs-branch.tistory.com


이제 페이징 처리를 화면에서 보여주는 작업을 해볼 것이다💁‍♀️

페이징 화면 처리 시에 필요한 정보들은 다음과 같다.
- 현재 페이지 번호 (page)
- 이전 링크 표시 여부 (prev)
- 다음 링크 표시 여부 (next)
- 화면에 보이는 시작 번호 (startPage)
- 화면에 보이는  끝 번호 (endPage)


페이징 처리를 하기 위해서 우선적으로 필요한 정보는 현재 사용자가 보고있는 페이지의 정보이다.
예를 들어, 시작 페이지를 보고있는 경우 화면의 페이지 번호는

1부터 시작할 것이고, 끝 페이지를 보고 있는 경우 화면의 페이지 번호는

14번부터 시작하고 있다. (물론 이거는 티스토리 스킨 설정에 따라 다르겠지만)
이런 식으로 어떤 페이지를 보고있냐에 따라 화면에 보여주는 페이지 링크들이 다르기 때문에 이 부분을 고려해야 한다.

화면 상에서 보이는 마지막 번호 계산

// 화면 상에서 보이는 끝 번호 구하는 공식 
this.endPage = (int)(Math.ceil(페이지번호 / 10.0)) * 10;


시작번호 계산 (만일 화면에 10개씩 보여준다면 시작번호는 무조건 끝 번호에서 9를 뺀 값이 된다.)

this.startPage = this.endPage - 9;


전체 페이지의 끝 번호 계산

// 전체 데이터 수에 의해 영향을 받는 끝 번호에 대해 다시 계산하는 작업 
realEnd = (int)(Math.ceil( total*1.0 / amount )); 
if(this.endPage > x){ 
	this.endPage = realEnd; 
}


이전(prev) 페이지 계산

this.prev = this.startPage > 1;


다음(next) 페이지 계산

this.next = this.endPage < realEnd;


(prev랑 next는 boolean 타입)


클래스 설계


domain패키지에 PageDTO.java를 추가한다.

@Getter
@ToString
public class PageDTO {
	private int startPage;
	private int endPage;
	private boolean prev, next;
	private int total;
	private Criteria cri;

	public PageDTO(Criteria _criteria, int _total) {
		this.cri = _criteria;
		this.total = _total;
		this.endPage = (int) (Math.ceil(_criteria.getPageNum() / 10.0)) * 10;
		this.startPage = this.endPage - 9;
		int realEnd = (int) (Math.ceil((_total * 1.0) / _criteria.getAmount()));
		if (realEnd < this.endPage) {
			this.endPage = realEnd;
		}
		this.prev = this.startPage > 1;
		this.next = this.endPage < realEnd;
	}
}


👇 DTO에 대한 설명이 필요한 경우 확인

더보기

DTO

Data Transfer Object

= 데이터를 전달하고 주고받을 때는 새로 클래스를 만들어서 하자, 기존에 있는 클래스는 사용하지 말자

 

데이터베이스에서 read, update작업을 할 때 VO클래스를 함부로 사용하였다가 다른사람이 실수로 데이터를 잘못 건드리는 경우에 시스템에 오류가 날 가능성이 높다. DB의 정보가 변경되는 것은 위험한 일이기 때문이다.

그래서 DB에 연결된 클래스는 그대로 두고, 정보를 교류하는 용도로만 따로 작성하여 사용하는 것이 DTO이다.


BoardController클래스에서 PageDTO를 사용할 수 있도록 Model에 담아서 화면에 전달해주어야 함
BoardController.java

@GetMapping("/list") // 조회하는 경우에는 get방식을 사용 
public void list(Criteria cri, Model model) { 
    log.info("[CONTROLLER]get list..." + cri); 
    model.addAttribute("list", service.getList(cri)); 
    model.addAttribute("pageMaker", new PageDTO(cri, 123)); 
    // pageDTO객체를 구성하기 위해서는 전체 데이터 수가 필요한데, 
    //아직 그 처리가 이루어지지 않았으므로 임의의 값으로 123을 지정 
}


list.jsp 하단에 페이징을 보여줄 위치에 아래의 코드를 붙여넣는다.

<!-- Paging --> 
<nav class="page navigation"> 
    <ul class="pagination"> 
        <c:if test="${pageMaker.prev}"> 
            <li class="paginate_button previous">
                <a class="page-link" href="#">Prev</a>
            </li> 
        </c:if> 
        <c:forEach var="num" begin="${pageMaker.startPage }" end="${pageMaker.endPage }"> 
            <li class="paginate_button">
                <a class="page-link" href="#">${num}</a> 
            </li>
        </c:forEach>
        <c:if test="${pageMaker.next}"> 
            <li class="paginate_button next">
                <a class="page-link" href="#">Next</a>
            </li>
        </c:if> 
    </ul> 
</nav> 
<!-- /.page -->


👇 페이징 부분이 가운데 정렬이 되게 하고 싶은 경우 css

더보기
<style> 
nav.page.navigation { 
	display: flex; justify-content: center; 
} 
</style>


list.jsp에서 붙여넣은 코드에 링크를 연결하는 작업이 필요하다.
아래의 이미지처럼 10페이지 이후 11페이지가 존재하는 경우에 Next버튼이 활성화되고,

11페이지로 넘어간 경우 Next버튼은 비활성화, Prev버튼이 활성화되도록 <c:if>태그를 사용하여 제어해주었다.

<c:forEach>태그로는 화면 상에 나열된 페이지번호들을 순차적으로 검사하여 pageNum이 num과 일치하는 경우 class="active"(해당하는 페이지 번호에 색칠됨)가 되도록 수정한다.

<!-- Paging --> <nav class="page navigation"> <ul class="pagination"> <c:if test="${pageMaker.prev}"> <li class="paginate_button previous"> <a class="page-link" href="${pageMaker.startPage - 1}">Prev</a> </li> </c:if> <c:forEach var="num" begin="${pageMaker.startPage}" end="${pageMaker.endPage}"> <li class="paginate_button ${pageMaker.cri.pageNum == num ? "active" : "" } "> <a class="page-link" href="${num}">${num}</a> </li> </c:forEach> <c:if test="${pageMaker.next}"> <li class="paginate_button next"> <a class="page-link" href="${pageMaker.endPage + 1}">Next</a> </li> </c:if> </ul> </nav> <!-- /.page -->


이대로 실행해보면 url경로가 /list를 포함하지 않기 때문에 get방식으로 /list를 호출해야 한다.
pageNum과 amount값의 속성은 hidden으로 처리해서 화면상에 나타나지 않게 한다.

<form id='actionForm' action="/board/list" method="get"> <input type="hidden" name="pageNum" value="${pageMaker.cri.pageNum}"> <input type="hidden" name="amount" value="${pageMaker.cri.amount}"> </form>


<form>으로 전달한 데이터를 자바스크립트로 처리해준다.

var actionForm = $('#actionForm'); $('.paginate_button a').on('click', function(e) { e.preventDefault(); //걸어둔 링크로 이동하는 것을 일단 막음 actionForm.find('input[name="pageNum"]').val($(this).attr('href')); actionForm.submit(); });

 

댓글