프로젝트

가전제품 대여 웹사이트 (세숫대여) - 자유게시판 페이징 기능 구현

sejin2 2023. 9. 28. 22:40

오늘은 게시판 하단에 페이징 기능을 구현하는 작업을 했다. 

먼저, 패키지 하나를 생성하고 페이징 기능을 구현할 class 를 생성하고, 

하단의 코드를 작성해야하지만 수업 때 사용했던 자료가 있어서 가지고 왔다. 

package com.rentalproject.ui;

public class ThePager {
	
	private int pageSize;//한 페이지당 데이터 개수
	private int pagerSize;//번호로 보여주는 페이지 Link 개수
	private int dataCount;//총 데이터 수
	
	private int pageNo;//현재 페이지 번호
	private int pageCount;//총 페이지 수
	
	private String linkUrl;//페이저가 포함되는 페이지의 주소
	
	
	public ThePager(int dataCount, int pageNo, int pageSize, int pagerSize, String linkUrl) {
		
		this.linkUrl = linkUrl;
		
		this.dataCount = dataCount;
		this.pageSize = pageSize;
		this.pagerSize = pagerSize;
		this.pageNo = pageNo;		
		pageCount = (dataCount / pageSize) + ((dataCount % pageSize) > 0 ? 1 : 0); 
	}
	
	public String toString(){
		StringBuffer linkString = new StringBuffer(2048);
		
		//1. 처음, 이전 항목 만들기
		if (pageNo > 1) {
			linkString.append(
				String.format("<a href='%s?pageNo=1' class='btn btn-outline-primary'>처음</a>",linkUrl));
			linkString.append("&nbsp;");
			linkString.append("&nbsp;");
			linkString.append(String.format(
				"<a href='%s?pageNo=%d' class='btn btn-outline-primary'>이전</a>", linkUrl, pageNo - 1));
			linkString.append("&nbsp;");
		} else {
			linkString.append("<span class='btn btn-outline-primary'>처음</span>");
			linkString.append("&nbsp;");
			linkString.append("&nbsp;");
			linkString.append("<span class='btn btn-outline-primary'>이전</span>");
			linkString.append("&nbsp;");
		}
		
		//2. 페이지 번호 Link 만들기
		int pagerBlock = (pageNo - 1) / pagerSize;
		int start = (pagerBlock * pagerSize) + 1;
		int end = start + pagerSize;
		for (int i = start; i < end; i++) {
			if (i > pageCount) break;
			linkString.append("&nbsp;");
			if(i == pageNo) {
				linkString.append(String.format("%d", i));
			} else { 
				linkString.append(String.format(
					"<a href='%s?pageNo=%d'>%d</a>", linkUrl, i, i));
			}
			linkString.append("&nbsp;");
		}
		
		//3. 다음, 마지막 항목 만들기
		if (pageNo < pageCount) {
			linkString.append("&nbsp;");
			linkString.append(String.format(
				"<a href='%s?pageNo=%d' class='btn btn-outline-primary' s>다음</a>",linkUrl, pageNo + 1));
			linkString.append("&nbsp;");
			linkString.append("&nbsp;");
			linkString.append(String.format(
				"<a href='%s?pageNo=%d' class='btn btn-outline-primary'>마지막</a>", linkUrl, pageCount));
		} else {
			linkString.append("<span class='btn btn-outline-primary'>다음</span>");
			linkString.append("&nbsp;");
			linkString.append("&nbsp;");
			linkString.append("<span class='btn btn-outline-primary'>마지막</span>");
			linkString.append("&nbsp;");
		}
		
		return linkString.toString();
	}

}

FreeBoardService.java

List<FreeBoardDto> listFreeBoardByPage(int from, int count);

FreeBoardServiceImpl.java

@Override
	public List<FreeBoardDto> listFreeBoardByPage(int from, int count) {
		List<FreeBoardDto> freeBoardList = freeboardMapper.selectFreeBoardByPage(from, count);
		return freeBoardList;
	}

FreeBoardMapper.java

@Select("select freeBoardNo, memberNo, freeBoardTitle, freeBoardViewCount, freeBoardDate, freeBoardDelete "  
			+ " from FreeBoard "
			+ "order by freeBoardNo desc "
			+ "limit #{from}, #{count}")

	List<FreeBoardDto> selectFreeBoardByPage(@Param("from") int from, @Param("count") int count);

여기서  limit는 my sql 에서만 쓸 수 있는 구문으로, SELECT 쿼리문에서 테이블 조회 시 출력할 레코드의 개수를 지정하고 그 개수만큼 제한하여 조회할 수 있다. 

FreeBoardController.java

@GetMapping(path= {"/freeboardlist"})
	public String list(@RequestParam(defaultValue = "1") int pageNo, Model model) { 
		
		List<FreeBoardDto> freeBoardList = freeBoardService.listFreeBoard();  // 전체 게시물 조회
		
		int pageSize = 10; // 한 페이지에 표시될 게시물의수 
		int pagerSize = 5; // 표시할 페이지 번호 개수 
		String linkUrl = "freeBoardlist"; // list?pageNo=3과 같은 형식으로 href 값 생성

FreeBoardService.java

int getFreeBoardCount();

FreeBoardServiceImpl.java

	@Override  //페이징 - 총 게시물 개수를 db에서 가지고 오기 
	public int getFreeBoardCount() {
		int count = freeboardMapper.selectFreeBoardCount();
		return count;
	}

FreeBoardMapper.java

	@Select("select count(*) from FreeBoard")
	int selectFreeBoardCount();

FreeBoardController.java

	// 자유게시글 리스트 화면 불러오기 ( 전체 게시글 불러오기 )
	@GetMapping(path= {"/freeboardlist"})
	public String list(@RequestParam(defaultValue = "1") int pageNo, Model model) { 
		
		//List<FreeBoardDto> freeBoardList = freeBoardService.listFreeBoard();  // 전체 게시물 조회
		
		int pageSize = 10;
		int pagerSize = 5;
		String linkUrl = "freeboardlist";
		int dataCount = freeBoardService.getFreeBoardCount();  // 총 게시물 개수 (DB에서 조회해야하는 내용)
		
		int from = (pageNo -1) * pageSize;  // 현재 페이지에 표시될 첫 번째 게시물 순서 번호 
		List<FreeBoardDto> freeBoardList = freeBoardService.listFreeBoardByPage(from, pageSize);
		
		ThePager pager = new ThePager(dataCount, pageNo, pageSize, pagerSize, linkUrl);
		
		 
		model.addAttribute("freeBoardList", freeBoardList);
		model.addAttribute("pager", pager);
		model.addAttribute("pageNo", pageNo);   //페이지 번호 표시기 만들기 
		
		return "freeboard/freeboardlist";
	}

페이징 기능 기본 구현 작업 후 freeboardlist.jsp로 가서 

 <table class="table align-items-center table-flush">
           <thead class="thead-light">
             <tr style="text-align:center;">
               <th scope="col" style="width:100px; font-size:10pt">게시글 번호</th>
               <th scope="col" style="width:500px; font-size:10pt">게시글 제목</th> 
               <th scope="col" style="width:200px; font-size:10pt">작성자</th>
               <th scope="col" style="width:100px; font-size:10pt">조회수</th>
               <th scope="col" style="width:150px; font-size:10pt">게시글 작성 일자</th>
             </tr>
           </thead>
           <tbody>
            <c:forEach var="freeBoard" items="${ requestScope.freeBoardList }">
             <tr style="text-align:center">
                <td scope="col" style="width:100px">${ freeBoard.freeBoardNo } </td>
                <td scope="col" style="width:500px"> 
                <c:choose>
                	<c:when test="${ not freeBoard.freeBoardDelete }">
                	<a href="freeboarddetail?freeBoardNo=${ freeBoard.freeBoardNo }&pageNo=${ pageNo }"> ${ freeBoard.freeBoardTitle }</a>  <!-- 삭제 아닐때 그냥 제목 보이기 -->
                	</c:when>
                	<c:otherwise>
                	<span class="freeBoardDelete" style="color : gray"><< 삭제된 게시글입니다 >></span> <!-- 삭제된 글 화면 보이기 -->
                	</c:otherwise>
               	</c:choose>
                </td>
                <td scope="col" style="width:200px"> ${ freeBoard.freeBoardDelete? '' : sessionScope.loginuser.memberId } <!-- 게시글 삭제시 작성자 안보이게 설정 -->
		                							 <input type="hidden" name="memberNo" value="${ loginuser.memberId }"> 
		                							 <!-- 오류 : 다시확인 로그인한 유저로 걍 다 바뀜 -->
                
                <td scope="col" style="width:100px">${ freeBoard.freeBoardViewCount } </td>
                <td scope="col" style="width:150px"><fmt:formatDate value="${ freeBoard.freeBoardDate }" pattern="yyyy-MM-dd HH:mm"/></td>
             </tr>
            </c:forEach>
                </tbody>
              </table>
              	<br><br>
                 ${ pager }
                 <br /><br />

</table> 하단에 페이저를 연결해주었다.

그리고 관련 페이지 조회시 freeBoardNo 뿐만 아니라 pageNo도 같이 조회되도록 url 부분에 다 pageNo 값을 넣어주었다. 

return String.format("redirect:/freeboard/freeboardlist?pageNo=%d", pageNo);

현재 페이지가 조금 진하게 표시 되고, 주소창에도 페이지번호가 잘 들어오는 것을 확인할 수 있다.