63. 스프링으로 게시물 리스트 페이징하기

hanahana·2022년 9월 8일
0

Spring 학원수강

목록 보기
14/45
post-thumbnail

페이징을 하러면 어떻게 해야할까?

  • 페이징은 어렵다 슬프지만 그렇다
  • 페이징을 하려면 알아야 할것은 무엇인가?
  1. 한페이지에 출력할 게시물의 갯수를 정한다
  2. 한 페이지에 출력할 페이지의 갯수를 정한다.
  3. 총 페이지 수를 파악한다.
  4. 현재 페이지를 서버에 알려줘야 한다.
  5. 서버에서 한 페이지에 출력할 게시물의 수만 넘겨줘야 한다.

자 이제 페이지를 만들어 보자

Controller에서 페이지를 계산하자

//게시물 출력코드
	@RequestMapping(value="/board/list.kh", method =RequestMethod.GET)
	public ModelAndView boardList(ModelAndView mv,
			@RequestParam(value="page", required=false) Integer page) {
		//@RequestParam(value="page", required=false)의 값은 page이지만 
		// required=false 필수값은 아니라는 뜻
		
		int currentPage = (page != null) ? page: 1;
		//현재 페이지
		//만약 page값이 없으면 기본형 1로 출력할것, 아니면 받아온 page의 값을 준다.
		//삼항연상자 사용
		
		int totalCount = bService.getTotalCount();
		int boardLimit = 10; //한 화면에 출력할 게시물 수
		int naviLimit = 5; //한 화면에 출력할 게시판 페이지 수
		int maxPage; //게시판의 총 페이지 수
		int startNavi; //한 화면에 출력되는 게시판 페이지의 처음 수
		int endNavi;//한 화면에 출력되는 게시판 페이지의 마지막 수
		
		maxPage =(int)((double)totalCount/boardLimit+0.9);
		startNavi = ((int)((double)currentPage/naviLimit+0.9)-1)*naviLimit+1;
		endNavi=startNavi+naviLimit-1;
		
		//endNavi가 maxNavi보다 커지는 오류방지
		if(maxPage<endNavi) {
			endNavi = maxPage;
		}
		
		
		List<Board> bList = bService.printAllBoard(currentPage, boardLimit);

		if(!bList.isEmpty()) {
			mv.addObject("startNavi",startNavi);
			mv.addObject("endNavi", endNavi);
			mv.addObject("maxPage",  maxPage);
			mv.addObject("bList", bList);
			
		}
		
		mv.setViewName("/board/listView");
		
		return mv;
		
		
		
	}
  • 매개변수의 값이 많이 증가했다.
  • public ModelAndView boardList(ModelAndView mv, @RequestParam(value="page", required=false) Integer page)
    • ModelAndView는 아까 선언했다
    • RequestParam으로 “page”라는 값을 받아왔다,
    • 이것은 jsp에서 get으로 받을값인데 이동할 page의 값을 주소로 받을것이다.
      • <a href = “/board/list.kh?page= 이동할페이지 >
      • 이 주소로 연결하면 get방식으로 page의 값을 컨트롤러가 받을수있다.
    • page의 값은 받지 않을수도 있다 required=false
    • page의 값을 null로 받을수 있도록 Integer로 선언해준다.
  • 현재 페이지를 알아야 한다. 현재 페이지는 CurrnetPage라는 이름으로 선언했다.
  • CurrentPage는 기본적으로 list.kh로 진입했을때 1페이지여야 하며, 페이지를 선택해 클릭했을때 나오는그 페이지이기때문에 page라는 변수로 받아온 바로 그 값이어야 한다!
    • [1][2] [3][4] 페이지중 3을 눌렀다면 3은 controller에 page라는 이름으로 전송되며 사용자가 바로 볼 현재페이지는 3이어야 한다.
    • 이 조건을 삼항 연산자로 표현하였다.
      • int currentPage = (page != null) ? page: 1;
      • 페이지의 값이null이 아니면 페이지는 사용자가 전송한값, null이면 기본값 1
  • 이제 페이지를 나눌 준비를 하자, 페이징을 할때 알아야 할것.
    1. 총 게시물의 수
    2. 한 페이지의 출력할 게시물의 수
    3. 한 페이지에 페이징할 게시판 페이지의 수
    4. 총 게시판의 페이지 수
  • 1번을 알기위한 코드가 int totalCount = bService.getTotalCount(); 이것이다.

총 게시물 수를 알기위해 service와 store로 간다.

Service

@Override
	public int getTotalCount() {
		int count = bStore.selectTotalCount(session);
		return count;
	}
  • 세션만 넘겨주고 store로

Store

@Override
	public int selectTotalCount(SqlSessionTemplate session) {
		int count = session.selectOne("BoardMapper.selectBoardCount");
		return count;
	}

session에서 연결한 select태그의 BoardMapper 라는 nameSpace에 selectBoardCount라는 id를 가진 쿼리문을 실행할것이다.

Mapper

<!-- 숫자 반환할거니까 resultTypeuploadFile="_int" 기억할것! -->
<select id="selectBoardCount" resultType="_int">
select count(*) from board_tbl where b_status = 'Y'

</select>
  • select태그는 항상 resultMap을 사용하여 값을 반환했는데 이번에는 count를 이용하여 총 게시물의 숫자를 파악하기때문에 숫자가 반환된다,
  • 숫자가 반환될떄는 resultType="_int" 으로 선언해주어야 한다.
  • b_status = 'Y' 는 삭제 처리 하지 않아다는 뜻이다, 게시물을 삭제할때 지워버릴수도 있지만 N으로 표시해 데이터베이스에는 남겨놓고 출력하지 않을수도 있다.

총 게시물수를 알았다. 이제 게시물 수를 가지고 페이징 계산을 다시 하자

		
		int totalCount = bService.getTotalCount();
		int boardLimit = 10; //한 화면에 출력할 게시물 수
		int naviLimit = 5; //한 화면에 출력할 게시판 페이지 수
		int maxPage; //게시판의 총 페이지 수
		int startNavi; //한 화면에 출력되는 게시판 페이지의 처음 번호
		int endNavi;//한 화면에 출력되는 게시판 페이지의 마지막 번호
  • 이제 한 화면에 출력할 게시물수를 10개
  • 한 화면에 출력할 게시물의 페이지수를 5개로 정했다.
  • 게시판의 총 페이지수와 한 화면에 출력될 첫 게시판 페이지 번호, 마지막 페이지번호를 구해보자
		maxPage =(int)((double)totalCount/boardLimit+0.9);
		startNavi = ((int)((double)currentPage/naviLimit+0.9)-1)*naviLimit+1;
		endNavi=startNavi+naviLimit-1;
		
		//endNavi가 maxNavi보다 커지는 오류방지
		if(maxPage<endNavi) {
			endNavi = maxPage;
		}
		
  • 총 페에지 번호는 총 게시물수를 출력할 게시물 수로 나눈 뒤 0.9를 더하고 나머지를 버리면하면 나온다
    • 예) 총 게시물 수 25개 한페이지에 출력할 게시물 수 6개 그 경우 페이지 수는 총 5페이지
    • 따라서 25/6 = 4.15 여기서 0.9를 더하고 5.05 나머지인 0.5를 버림하면 내가 원하는 페이지수 5가나온다.
  • 페이지에 출력할 첫 페이지의 번호, 1~5 페이지까지는 첫 페이지가 1이고 6~10 페이지의 첫페이지는 6, 11부터 15페이지의 첫페이지는 11일것이다.
  • 그렇기때문에 현재 페이지가 12이라고 가정할때 첫 페이지는 11이어야 한다
    • 계산해보자 12/5 = 2.4 여기에 0.9를 더하면 3.3, 여기에서 1을빼면 2.3이다
    • int로 형변환 할것이기에 계산값은 2가 되고 다시 5를 곱하면 10여기에 1을 더하면 11
    • 원하는 첫 페이지의 값이 나온다.
  • 마지막 페이지의 값은 첫페이지값에서 출력할페이지값 -1을 해주면 된다.

이제 다시 목록을 받아오자

  • 데이터베이스에서 한페이지에 출력될 만큼의 게시물만 반환해주어야 한다.
		List<Board> bList = bService.printAllBoard(currentPage, boardLimit);

		if(!bList.isEmpty()) {
			mv.addObject("startNavi",startNavi);
			mv.addObject("endNavi", endNavi);
			mv.addObject("maxPage",  maxPage);
			mv.addObject("bList", bList);
			
		}
		
		mv.setViewName("/board/listView");
		
		return mv;
		
  • 데이터베이스에서 보낸 List값을 다시 보내 반환받고
  • 값이 있을때 modelAndView를 이용해 방금 정한 출력할 게시물 페이지 번호를 listView.jsp로 보내주면 된다.
  • 이때 필요한 현재페이지(사용자가 출력하고자 누른페이지 번호) 와 한 화면에 출력할 게시물수를 전달한다

Service로 가보자

@Override
	public List<Board> printAllBoard(int currentPage, int limit) {
		List<Board> bList = bStore.selectAllboard(session,currentPage,limit);
		return bList;
	}
  • 세션과 전달받은 값을 전송한다, limit로 전달한다 이름은 중요하지 않지만 spring에서 이런 키워드로 인식해서 맞춰줬다.

Store에서 처리한다.

@Override
	public List<Board> selectAllboard(SqlSessionTemplate session, int currentPage, int limit) {
		//offset currentPage에 의해서 변경되는 값
		//1->1, 2->11, 3->21 게시판 페이지에서 처음의 출력되는 게시물의 번호
		//limit는 한 페이지당 보여주고 싶은 게시물의 갯수
		//지금은 10
		
		//RowBounds란 쿼리문을 변경하지 않고도 페이징을 처리할수 있게 해주는 클래스이며
		//offset과 limit값을 이용해서 동작함, offset은 currentPage에 의해서 변하는 값이고
		//limit값은 고정값이다

		//offset은 0, 10 , 20으로 currentPage에서 실제로 2페이지에 출력하는 첫 게시물의 번호인 11 보다 1작다
		int offset = (currentPage-1)*limit;
		RowBounds rowBounds= new RowBounds(offset,limit);
		List<Board> bList = session.selectList("BoardMapper.selectAllBoard",null,rowBounds);
		return bList;
	}
  • offset이라는 페이지를 이동할때 맨 처음 보이는 게시물 순서의 번호를 계산한다.
  • 1페이지 일대는 1번게시물 2페이지일때는 11번 3페이지일때는 21번 일것이다.
  • 이 값을 계산하는 방법은 현재페이지에서 1을빼고 한페이지 당 보이는 게시물수를 곱하면 된다,.
  • RowBounds라는 spring의 클래스를 이용한다
    • 이렇게 구한 offset limit를 이 클래스의 매개변수로 지정하면 spring에서 페이지에서 출력할 게시물을 계산해 전달해준다.
    • session.selectList("BoardMapper.selectAllBoard",null,rowBounds);
    • 쿼리문은 바뀌지 않으며 중간에 null을 넣어줘야 계산이 된다.

jsp의 c:if문을 사용한다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>자유게시판</title>
</head>
<body>
	<h1 align="center">게시글 목록</h1>
	<br>
	<br>
	<table align="center" border="1">
		<tr>
			<th>번호</th>
			<th>제목</th>
			<th>작성자</th>
			<th>날짜</th>
			<th>조회수</th>
			<th>첨부파일</th>
		</tr>

		<c:forEach items="${bList }" var="board" varStatus="i">
			<tr>
				<td>${i.count }</td>
				<td>${board.boardTitle }</td>
				<td>${board.boardWirter }</td>
				<td>${board.bCreateDate }</td>
				<td>${board.boardCount }</td>
				<td>0</td>
			</tr>
		</c:forEach>

<!----------------------------------페이징시작-------------------------------------->
		<tr align="center" height="20">
			<td colspan="6">
			
			<!-- 	startNavi가 1일이 아닐때만 출력 -->
			<c:if test="${startNavi ne 1 && startNavi > 0}">
			<a href="/board/list.kh?page=${startNavi-1 }">이전</a>
			</c:if>
			
			
			<!-- p는 기준을 삼을 임시변수 startNavi부터 시작해 endNavi까지 출력한다 -->
			<c:forEach var="p" begin="${startNavi }" end="${endNavi }" >
			<a href="/board/list.kh?page=${p }">${p }</a>
			</c:forEach>
			
			
			
			<!-- 	endNavi가 maxPage와 같지 않을때만 출력 -->
			<c:if test="${endNavi ne maxPage }">
			<a href="/board/list.kh?page=${endNavi+1 }">다음</a>
			</c:if>
			
			</td>
	</table>
</body>
</html>
  • 반환받은 bList값을 이용해 아까처럼 게시물을 출력하지만 이번엔 정확히 페이지에 맞는 10개의 게시물만 반환해준다.
  • [이전]페이지는 startNavi가 1일땐 출력되지 않는다.
    • <c:if test="${startNavi ne 1 && startNavi > 0}">
    • /board/list.kh?page=${startNavi-1 } : 이전은 페이지의 시작페이지번호 -1이다
  • [다음]은 마지막 페이지수가 총 페이지수와 같으면 출력되지 않는다
    • <c:if test="${endNavi ne maxPage }">
    • <a href="/board/list.kh?page=${endNavi+1 }"> 다음은 페이지의 마지막페이지번호 +1이다
  • list.kh에서 받아온 변수의 값이 헷갈리면 controller를 한번 확인해보면 된다! 거기에 뭔지 다 써있음!
profile
hello world

0개의 댓글