스프링 #17 페이징 화면처리(현재 게시글 조회 to 해당 목록페이지 이동)

수박·2020년 6월 10일
0

Spring

목록 보기
16/18

스프링 #17 페이징 화면처리

http://localhost:8090/board/list?pageNum=3

이전까지의 내용은 해당 값으로 브라우저에 요청을 하면 페이징을 나누어 이동할 수 있었다.

이번에는 밑에 페이지번호를 추가하여 클릭시 해당 페이지로 이동할 수 있도록 하는 것을 구현하고자 한다.

다음 과정을 통해 진행한다.

  1. 브라우저 주소창에서 페이지 번호를 전달해 결과를 확인
  2. JSP에서 페이지 번호를 출력
  3. 각 페이지 번호에 클릭 이벤트 처리
  4. 전체 데이터 갯수를 반영해 페이지 번호 조절

페이징은 단순 링크연결이지만, 조회, 수정, 삭제페이지까지 페이지 번호가 계속 유지되어야 하기 때문에 이를 신경써야 한다.

페이징을 위한 필요한 정보

  • 현재 페이지 번호
  • 이전, 다음으로 이동 가능한 링크 표시여부(prev, next)
  • 화면에서 보여지는 페이지 시작, 끝 번호(startPage, endPage)

끝, 시작 페이지 번호

시작보다 끝 페이지 번호를 먼저 구하는 것이 수월하다.

this.endPage = (int)(Math.ceil(페이지번호 / 10.0)) * 10;

10페이지씩 나눈다고 가정한 코드

ceil은 소수점 올림으로 처리한다.

ceil(0.1) = 1

ceil(1) = 1

ceil(1.1) = 2

그러므로 페이지번호가 1~10까진 마지막페이지가 10페이지, 11~20까진 20페이지로 계산할 수 있다.

그러나 페이지수가 10개가 되지 않으면 끝 번호가 10으로 끝나면 되면 안된다. 그럼에도 끝을 먼저 구하는 이유는 시작페이지번호 계산이 수월해지기 때문이다.

this.startPage = this.endPage - 9;
  • 시작번호는 1, 11, 21.. 이렇게 지정됨

그렇다면 시작번호를 수월하게 구했으니, 전체 데이터 수(total)를 이용해 진짜 마지막 페이지를 구해본다.

total이 80이었을 떄 마지막 번호는 10이아닌 8이되어야한다.

if 이렇게 해서 구한 값이 원래 endPage(10)보다 작으면 endPage값을 8로 변경한다.

realEnd = (int)(Math.ceil(total * 1.0)) / amount));//total이 8일 때 8페이지, 81이면, 9페이지가 됨

if(realEnd < this.endPage)//realEnd가 10보다 작다면, endPage는 작은 값으로 변경
	this.endPage = realend;

이전, 다음

이전 값은 시작 번호가 1보다 큰 경우일 때 존재한다.

2페이지일 때 1페이지로 넘어가기 위해서.

this.prev = this.startPage > 1;

다음 값은 realEnd가 끝 번호보다 큰 경우에만 존재한다.

현재 2페이지이면, endPage는 10일 때, realEnd가 8페이지 밖에 없다면 다음으로 넘어가는 값은 존재하지 않는다.

realEnd가 22페이지라면 다음으로 넘어가는 값이 필요하다.

this.next = this.endPage < realEnd;

페이징 처리를 위한 클래스 설계

domain에 PageDTO클래스를 작성한다.

@Data
public class PageDTO {

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

여기서 계산된 값들을 Controller에서 View로 전달하기 위해 model에 담아야한다. list메소드를 수정한다.

	@GetMapping("/list")
	public void list(Criteria cri, Model model)
	{
		log.info("list: "+ cri);
		model.addAttribute("pageMaker", new PageDTO(cri, 123));
		model.addAttribute("list", service.getList(cri));
	}
	
  • 생성자에서 전체 데이터(total)을 가져와야 하는 부분을 추가해야한다.

JSP에서 페이지 번호 출력

테이블 하위단에 해당 JSP를 작성한다.

		<div class="pull-right">
			<ul class="pagination">
				<c:if test="${pageMaker.prev }">
					<li class="paginate_button previous" ><a href="#">Previous</a>
				</c:if>
				
				<c:forEach var="num" begin="${pageMaker.startPage }"
					end="${pageMaker.endPage }">
					<li class ="paginate_button"><a href="#">${num }</a></li>
				</c:forEach>
				
				<c:if test="${pageMaker.next }">
					<li class="paginate_button next"><a href="#">Next</a></li>
				</c:if>
			</ul>
		</div>

페이지 번호 이벤트처리

	<li class ="paginate_button" ${pageMaker.cri.pageNum == num ? "active":"" }"><a href="${num }">${num }</a></li>
<li class="paginate_button next"><a href="${pageMaker.endPage + 1 }">Next</a></li>

a태그의 href속성값으로 번호만을 가지게 변경된다.

해당 버튼을 클릭시 /board/번호로 이동되는 것을 확인할 수 있다.

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

<script type="text/javascript">
	$(document).ready(function(){
		var actionForm = $("#actionForm");
		
		$(".paginate_button a").on("click", function(e){
			e.preventDefault();
			console.log('click');
			
			actionForm.find("input[name='pageNum']").val($(this).attr("href"));
			actionForm.submit();
		});
	});
</script>

pageNum, amount를 가진 form태그를 만든 후 페이지 버튼을 클릭했을때 이벤트를 처리하도록 스크립트를 작성한다.

해당 값을 가진 객체(actionForm)은 페이지 버튼(paginate_button)이 클릭되었을때, paginate_button의 a태그 href속성값을 actionForm의 pageNum에 넣고 get방식으로 /board/list에 제출한다.

controller의 GetMapping어노테이션을 가진 getList메소드는 해당하는 값을 cri객체에 매핑하고 이를 통해 목록을 출력하게 된다.

게시글을 눌렀을때 list버튼을 누르게 되면, 첫 페이지의 목록이 출력되는데 이는 default로 설정된 값이 cri에 있기 때문에 pageNum, amount를 get페이지에서 list로 넘겨주어야한다.

그렇다면 list페이지에서 게시글을 눌렀을때 현재의 pageNum과 amount를 넘겨주는 것 부터 진행해야한다.

	<td>
						<a class='move' href='<c:out value="${board.bno }"/>'>
						<c:out value="${board.title }"/>
						</a>
					</td>

기존에는 제목에 href링크를 걸어 bno값만 전달했지만 a태그로 클래스를 묶어서 스크립트에서 나머지 값까지 함께 전달할 것이다.

		$(".move").on("click", function(e){
			e.preventDefault();
			actionForm.append("<input type='hidden' name='bno' value='"+$(this).attr("href")+"'>");
			actionForm.attr("action", "/board/get");
			actionForm.submit();
		});

move버튼이 클릭되었을때, actionForm(pageNum, amount가 담겨있는 form태그)에다가 move라는 이름의 a태그안의 href속성값(c:out)을 가진 input 태그를 덧 붙인다.

actionForm의 속성값 action을 /board/get으로 지정한다.

actionForm을 해당 URL에 제출한다.

그렇다면 제목을 클릭했을때 move on Click이 실행되고, actionForm태그에 있는 내용 + bno값이 추가되어 controller의 get 메소드를 호출하게 된다.

	@GetMapping({"/get", "/modify"})
	public void get(@RequestParam("bno") int bno, @ModelAttribute("cri") Criteria cri, Model model) {
		log.info("get..modify.......: page : "+cri.getPageNum() +"amount"+ cri.getAmount());
		
		model.addAttribute("board", service.get(bno));
	}

컨트롤러의 get메소드는 ModelAttribute로 View에서 전달한 값을 Criteria에 매핑시킨다.

cri.get메소드를 수행하면 list페이지에서 전달한 값이 들어오는 것을 확인할 수 있다.


이제 앞서말한 조회페이지에서 list를 눌렀을 때 디폴트 페이지로 넘어가는 이슈를 해결해야한다.

마찬가지로 get페이지에서 pageNum, amount값을 넘겨준다.

get페이지에서는 operForm의 폼태그에 데이터를 담는다.

			<form id='operForm' action="/board/modify" method="get">
				<input type='hidden' id='bno' name='bno' value='<c:out value="${board.bno }"/>'>
				<input type='hidden' id='pageNum' name='pageNum' value='<c:out value="${cri.pageNum }"/>'>
				<input type='hidden' id='amount' name='amount' value='<c:out value="${cri.amount}"/>'>
			</form>

그리고 동작확인시 해당 게시글이 속한 페이지로 돌아가는 것을 확인할 수 있다.

0개의 댓글