[Spring] 게시판 페이징 처리

손영태·2022년 2월 8일
1

Spring 배우면서 페이징 처리가 어려워 정리해본다.
나는 페이징 숫자 5개까지만 출력하게 할 것이다.

ArticlePage.java

// 페이징 처리를 위한 클래스
// 게시글 데이터와 페이징 관련 정보를 담고 있음
public class ArticlePage {
	// 페이징 관련 멤버변수
	
	// 전체 글의 행의 수
	private int total;
	// 현재 페이지 번호
	private int currentPage;
	// 전체 페이지 개수
	private int totalPages;
	// 시작 페이지 번호
	private int startPage;
	// 종료 페이지 번호
	private int endPage;
	// 페이징의 개수
	private int pagingCount;
	// 게시글 데이터
	private List<LprodVO> content;
	
	// 생성자
	// size : 한 화면에 보여질 행의 수
	public ArticlePage(int total, int currentPage, int size, int pagingCount, List<LprodVO> content) {
		this.total = total;
		this.currentPage = currentPage;
		this.content = content;
		this.pagingCount = pagingCount;
		
		if(total == 0) { // select 결과가 없다면...
			totalPages = 0;
			startPage = 0;
			endPage = 0;
		} else { // select 결과가 있다면...
			// 전체 페이지 개수 구하기(전체 글의 수 / 한 화면에 보여질 행의 수)
			// 정수와 정수의 나눗셈의 결과는 정수이므로 13 / 7 = 1
			totalPages = total / size;
			// 보정해줘야 할 경우는? 나머지가 0보다 클 때
			if(total % size > 0) {
				// 전체페이지수를 1증가 처리
				totalPages++;
			}
			
			// startPage : '이전 [1] [2] [3] [4] [5] 다음' 일때 1을 의미
			// 공식 : 현재페이지 / 페이징의 개수 * 페이징의 개수 + 1;
			startPage = currentPage / pagingCount * pagingCount + 1;
			// 보정해줘야 할 경우는? 5 / 5 * 5 + 1 => 6 경우처럼
			// 					현재페이지 % 5 == 0 일 때 
			if(currentPage % pagingCount == 0) {
				// startPage = startPage - 5(페이징의 개수)
				startPage -= pagingCount;
			}
			
			// endPage   : '이전 [1] [2] [3] [4] [5] 다음' 일때 5을 의미
			endPage = startPage + pagingCount - 1 ;
			// 보정해줘야 할 경우는? endPage > totalPages 일때
			//					endPage를 totalPages로 바꿔줘야 함 
			if(endPage > totalPages) {
				endPage = totalPages;
			}
		}
	}
	
	// 전체 행의 수를 리턴
	public int getTotal() {
		return this.total;
	}
	
	// select 결과가 없는가? 체킹 : true면 결과가 없다는 의미
	public boolean hasNoArticles() {
		return this.total == 0;
	}
	
	// select 결과가 있는가? 체킹 : true면 결과가 있다는 의미
	public boolean hasArticles() {
		return this.total > 0;
	}
	
	// 현재 페이지 번호 리턴
	public int getCurrentPage() {
		return this.currentPage;
	}
	
	// 전체 페이지의 개수 리턴
	public int getTotalPages() {
		return totalPages;
	}
	
	// 데이터 VO List 리턴
	public List<LprodVO> getContent(){
		return this.content;
	}
	
	// 목록 하단의 시작 번호를 리턴
	public int getStartPage() {
		return this.startPage;
	}
	
	// 목록 하단의 종료 번호를 리턴
	public int getEndPage() {
		return this.endPage;
	}
	
}

class는 이런식으로 작성하였고 변수명들이 무엇을 의미하는지 주석처리하였다. 메소드 또한 주석처리했는데 어떤 변수와 메소드가 어떤 역할을 하는지 혼동하지 말고 기억하자.(제발..)

LprodController.java

@RequestMapping(value="/lprod")
@Controller
public class LprodController {
	private static final Logger logger = LoggerFactory.getLogger(LprodController.class);
	
	@Autowired
	LprodService lprodService;
	
	// http://localhost:8090/lprod/list?currentPage=1
	// defaultValue : 해당 요청 파라미터를 지정하지 않을 경우
	// defaultValue 속성에 지정한 문자열을 값으로 이용하게 됨
	@RequestMapping("/list")
	public String list(Model model, @RequestParam(defaultValue="1") int currentPage) {
		List<LprodVO> list = this.lprodService.list();
		logger.info("list.size() : " + list.size());
		// 상품 분류별 거래처 목록 행의 수
		int total = this.lprodService.listCount();
		logger.info("total : " + total);
		
		model.addAttribute("list", new ArticlePage(total, currentPage, 7, 5, list));
		
		model.addAttribute("total", total);
		
		// forward
		return "lprod/list";
	}
}

이 클래스는 Spring에 컨트롤러를 맡고 있다. @RequestParam에 defaultValue를 달아줬는데 이유는 파라미터를 주소에 넣지 않으면 오류가 뜨는 현상을 없애주기 위해서 삽입하였다. 이것을 넣음으로써 .../lprod/list를 주소창에 넣으면 1페이지를 자동 설정이 된다.
변수 list는 SQL mapper에서 작성한 쿼리를 통해 상품 정보를 가져온다.(Mapper 작성 생략, lprod테이블, buyer테이블...).
total 변수는 addAttribute로 넘겨주지 않아도 ArticlePage에서 getter메소드를 사용해서 받을 수 있다.(그냥 넣어봄)

model.addAttribute("list", new ArticlePage(total, currentPage, 7, 5, list));

이 코드에서는 list에 ArticlePage객체를 넣어준다. 매개변수는 순서대로 전체글 개수, 현재페이지, 한 화면에 출력해 줄 글 개수, 한 화면에 보여주는 페이징 숫자 개수, 전체글 리스트이다.

list.jsp

<div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
<ul class="pagination">
	<!-- Previous 시작 -->
	<li class="paginate_button page-item previous <c:if test='${list.startPage<6 }'>disabled</c:if>" id="dataTable_previous"><a href="/lprod/list?currentPage=${list.startPage-5 }" aria-controls="dataTable" data-dt-idx="0" tabindex="0" class="page-link">Previous</a></li>
	<!-- Previous 끝 -->
	<!-- Page번호 시작 -->
	<c:forEach var="pNo" begin="${list.startPage }" end="${list.endPage }" step="1">
		<li class="paginate_button page-item  <c:if test='${param.currentPage eq pNo }'>active</c:if>"><a href="/lprod/list?currentPage=${pNo }" aria-controls="dataTable" data-dt-idx="1" tabindex="0" class="page-link">${pNo }</a></li>
	</c:forEach>
	<!-- Page번호 끝 -->
	<!-- Next 시작 -->
	<li class="paginate_button page-item next <c:if test='${list.endPage>=list.totalPages }'>disabled</c:if>" id="dataTable_next"><a href="/lprod/list?currentPage=${list.startPage+5 }" aria-controls="dataTable" data-dt-idx="7" tabindex="0" class="page-link">Next</a></li>
	<!-- Next 끝 -->
</ul>
</div></div>

이번페이지 가기 버튼 Previous에서 봐야할 코드.
1.

<c:if test='${list.startPage<6 }'>disabled</c:if>

li태그 class속성에 들어있는 코드이다. 이전 페이지 가기버튼은 1 ~ 5페이지 안에 현재 페이지가 있다면 비활성화를 해야한다. 그렇기 때문에 startPage가 6보다 아래인 경우는 1밖에 없는데 그래서 저런식으로 조건을 달아 값이 true이면 disabled가 삽입되게 하였다.
2.

<a href="/lprod/list?currentPage=${list.startPage-5 }" aria-controls="dataTable" data-dt-idx="0" tabindex="0" class="page-link">Previous</a>

이 코드는 이전 버튼을 클릭했을때 현재페이지가 어디에서 활성화될지를 판단하는 태그이다.

  • 이전 버튼 누르기 전 사진
  • 이전 버튼 누른 후 사진

    이 사진은 13페이지에서 이전페이지를 눌렀을때 보이는 사진이다.
    보는 것처럼 11~15페이지에 있던 화면이 6~10페이지로 넘어가고 현재페이지는 6~10중에서 단순히 5를 빼준게 아닌 가장 첫번째인 6페이지에 활성화가 된다.
    그래서 a태그의 href속성은 startPage에서 5를 빼준페이지에 활성화 되게끔한다. ( 11~15페이지의 startPage는 11이고 여기서 5를 빼게되어 currentPage는 6이되게 된다. )
<c:forEach var="pNo" begin="${list.startPage }" end="${list.endPage }" step="1">

페이지 번호가 내가 5개로 설정을 해두어서 그냥 li태그를 5개 작성을 해도되지만 계속해서 숫자가 바뀌고 하기때문에 반복문을 사용해서 출력해준다.
begin속성은 startPage로 설정을 해주면서 1,6,11... 순으로 시작을 하게된다. end속성은 endPage로 설정을 하여 5,10,15.. 순으로 나오고 totalPages가 13이나 16 등의 숫자이면 그 숫자까지만 출력해준다.
4.

<li class="paginate_button page-item  <c:if test='${param.currentPage eq pNo }'>active</c:if>">

이 코드는 현재페이지를 파란색으로 활성화하여 보여주는 코드이다. class속성에 active를 넣을 경우 파란색으로 설정되겠끔 부트스트랩이 설정되어 있다. 그래서 파라미터로 받은 현재페이지와 출력하려는 페이지의 숫자가 같을 경우 active설정을 하게 한다.
조건문은 <c:if test="조건식">를 사용하여 출력해준다.
5.

<a href="/lprod/list?currentPage=${pNo }" aria-controls="dataTable" data-dt-idx="1" tabindex="0" class="page-link">${pNo }</a>

이 코드는 클릭시 currentPage에 숫자를 넣어 위에 4번 코드로 하여금 활성화 되게 해준다.
6.

<li class="paginate_button page-item next <c:if test='${list.endPage>=list.totalPages }'>disabled</c:if>" id="dataTable_next">

next버튼으로 '<c:if test='${list.endPage>=list.totalPages }'>disabled</c:if>'으로 총페이지 숫자를 페이징 마지막 숫자(5,10,15.. 등등)가 넘어서거나 같을 경우 비활성화를 시켜준다.
7.

<a href="/lprod/list?currentPage=${list.startPage+5 }" aria-controls="dataTable" data-dt-idx="7" tabindex="0" class="page-link">Next</a>

next의 버튼이 클릭시 이벤트를 주는 a태그이다. 이전버튼과 마찬가지로 누르면 다음 페이징들중에 가장 첫번째 페이지가 현재페이지로 설정되게 해준다.

지금까지 Spring에서 페이징 숫자 출력하는 방법이었다. 한페이지 당 7개 글이 올라와야하는데 아직 설정을 하지 못해서 다음 글 작성시 작성해 볼 생각이다.

0개의 댓글