본문 바로가기
[ View ]/JSP

[ JSP ] 게시판 만들기 6 - 페이지 나누기 기능 구현

by 환이s 2023. 4. 4.

이전 포스팅에서 답변 기능을 추가로 구현했습니다.

오늘은 게시판에 여러 정보들을 페이지 단위로 보여주기 위해 페이지네이션 기능을 구현합니다.

 

 

 

게시판 기능/ 파일 구조

 

< 기능 >

1 ) CRUD(글쓰기, 목록/상세, 수정, 삭제)

2 ) 검색 기능

3 ) 페이지 나누기

4) 파일 업로드, 다운로드

5 ) 댓글 달기

6 ) 답변 달기

 

< 파일 구조 >

Contoller

BoardController.java

Model

Pager.java Constants.java (상수값들)
BoardDTO.java
BoardCommentDTO.java(댓글 관련)
BoardDAO.java
board.xml

View

index.jsp : 시작 페이지
list.jsp : 게시판 목록
write.jsp : 글쓰기
comment_list.jsp : 댓글 목록
edit.jsp : 수정, 삭제 기능
reply.jsp : 답변 달기
search.jsp : 검색 페이지

 

페이지네이션 기능은 게시판 목록 페이지에서 필요한 기능이라서 폼 작업은 목록 페이지 list.jsp 파일에서 코드 작업을 합니다. 폼 작업을 하기 전에 필요한 공식, 상수값 설정 먼저 진행하겠습니다.


Pager.java

 

Pager 파일은 페이지네이션 기능 구현하는데 있어서 꼭 필요한 파일입니다.

 

페이지당 게시물 수, 블록 개수, 현재/다음/이전 페이지 등 기능 구현하는데 필요한 페이지입니다. 즉, 간단하게 설명하자면 페이지네이션 기능 구현에 필요한 공식 파일이라고 알고 계시면 될 거 같습니다.

 

각 기능들은 주석 처리로 설명을 넣었습니다.

 

package page;

public class Pager {
	public static final int PAGE_SCALE=10;//페이지당 게시물수(10개)
	public static final int BLOCK_SCALE=10;//페이지 블록 갯수
	private int curPage; //현재 페이지 
	private int prevPage; //이전 페이지
	private int nextPage; //다음 페이지
	private int totPage; //전체 페이지 갯수
	private int totBlock; //전체 페이지블록 갯수
	private int curBlock; //현재 페이지블록  
	private int prevBlock; //이전 페이지블록
	private int nextBlock; //다음 페이지블록
	private int pageBegin; // #{start}에 전달될 값
	private int pageEnd; // #{end}에 전달될 값
	private int blockStart; //페이지블록의 시작페이지 번호
	private int blockEnd; //페이지블록의 끝페이지 번호
	
	//getter,setter만 생성, 단 상수2개는(PAGE_SCALE,BLOCK_SCALE)빼고 만듦
	
	// Pager(레코드갯수, 보여줄페이지번호) 
	public Pager(int count, int curPage){
		curBlock=1; //페이지블록을 1로 초기화
		this.curPage=curPage; 
		setTotPage(count); //전체 페이지 갯수 계산
		setPageRange(); // #{start}, #{end} 값 계산
		setTotBlock(); // 페이지블록의 갯수 계산
		setBlockRange(); //페이지블록의 범위 설정
	}
	//페이지블록의 범위 설정 
	public void setBlockRange(){
		//현재페이지가 몇번째 페이지블록에 속하는지 계산
		//(현재페이지-1)/페이지블록단위 + 1
		curBlock=(int)Math.ceil((curPage-1) / BLOCK_SCALE)+1;
		//(현재블록-1)*블록단위+1
		blockStart=(curBlock-1) * BLOCK_SCALE + 1;
		//블록시작번호+(페이지블록단위-1)
		blockEnd=blockStart + (BLOCK_SCALE-1);
		//블록의 마지막 페이지번호가 범위를 초과하지 않도록 처리
		if(blockEnd > totPage){
			blockEnd = totPage;
		}
		//[이전] 11 12 13 14 15 16 17 18 19 20 [다음]
		//[이전]을 눌렀을 때 이동할 페이지, 현재블럭이 1이면 1로감,[이전]이란표시는 빼야함
		prevPage=curBlock==1 ? 1 : (curBlock-1) * BLOCK_SCALE;
		//[다음]을 눌렀을 때 이동할 페이지
		nextPage=curBlock>totBlock 
				? (curBlock*BLOCK_SCALE) : (curBlock*BLOCK_SCALE)+1;
		if(nextPage >= totPage){//다음페이지가 토탈페이지보다 크면 [다음]표시뺌
			nextPage = totPage;
		}
	}
	public void setPageRange(){
		//시작번호=(현재페이지 - 1 ) * 페이지당게시물수 + 1
		pageBegin = (curPage - 1) * PAGE_SCALE + 1;
		//끝번호=시작번호 + ( 페이지당게시물수 – 1 )
		pageEnd = pageBegin + (PAGE_SCALE - 1);
	}
	
	public int getCurPage() {
		return curPage;
	}
	public void setCurPage(int curPage) {
		this.curPage = curPage;
	}
	public int getPrevPage() {
		return prevPage;
	}
	public void setPrevPage(int prevPage) {
		this.prevPage = prevPage;
	}
	public int getNextPage() {
		return nextPage;
	}
	public void setNextPage(int nextPage) {
		this.nextPage = nextPage;
	}
	public int getTotPage() {
		return totPage;
	}
	//전체 페이지 갯수 계산
	public void setTotPage(int count) {
		// 991 / 10 => 99.1 올림 => 100
		// 991/10 => 99
		// 991.0/10 => 99.1
		//ceil() 올림, round() 반올림, floor() 버림 
		totPage = (int)Math.ceil(count * 1.0 / PAGE_SCALE);
	}
	public int getTotBlock() {
		return totBlock;
	}
	//페이지블록의 갯수 계산
	public void setTotBlock() {
		// 991페이지 : 991/10 => 99, 한페이지 누락이기때문에 올림(ceil)처리함
		totBlock = (int)Math.ceil(totPage * 1.0 / BLOCK_SCALE);
	}
	public int getCurBlock() {
		return curBlock;
	}
	public void setCurBlock(int curBlock) {
		this.curBlock = curBlock;
	}
	public int getPrevBlock() {
		return prevBlock;
	}
	public void setPrevBlock(int prevBlock) {
		this.prevBlock = prevBlock;
	}
	public int getNextBlock() {
		return nextBlock;
	}
	public void setNextBlock(int nextBlock) {
		this.nextBlock = nextBlock;
	}
	public int getPageBegin() {
		return pageBegin;
	}
	public void setPageBegin(int pageBegin) {
		this.pageBegin = pageBegin;
	}
	public int getPageEnd() {
		return pageEnd;
	}
	public void setPageEnd(int pageEnd) {
		this.pageEnd = pageEnd;
	}
	public int getBlockStart() {
		return blockStart;
	}
	public void setBlockStart(int blockStart) {
		this.blockStart = blockStart;
	}
	public int getBlockEnd() {
		return blockEnd;
	}
	public void setBlockEnd(int blockEnd) {
		this.blockEnd = blockEnd;
	}
	
	
}

 

위 코드 파일을 활용해서 list.jsp(목록 페이지)에서 폼 구현을 합니다.

 


list.jsp

 

페이지네이션 폼 구현은 EL, JSTL 기법을 응용해서 Pager 파일에 생성한 변수를 활용해서 코드 구현을 합니다.

 

 

위 코드를 보시면 onclick 처리를 list 함수로 통일했습니다. 그 이유는 자바 스크립트에서 list 함수를 한 번에 처리해서 Controller에서 작업하려고 합니다.

 

스크립트 코드를 보시면

 

 

list.do라는 가상의 주소를 보내서 요청을 했습니다. 이전 포스팅에서 목록 페이지 구현할 때 list.do 주소를 갖고 기능 구현을 했습니다.

 

즉, Controller에 있는 list.do에 페이지네이션 코드 작업을 추가해서 DAO에서 mapper 파일에 요청하면 됩니다.


Controller

 

먼저 list.do 처리했던 코드를 확인해 보면

 

 

해당 게시물 데이터 요청만 DAO에 보내서 목록 페이지로 구현할 수 있게 코드 작업을 했습니다.

그럼 여기서 추가로 페이지네이션 작업을 하기 위해 DAO에 추가 코드를 작업해서 요청을 보냅니다.

 

 

위 코드를 보면 먼저 레코드 개수를 계산하는 메서드를 생성해서 view단에서 요청 보낸 curPage 값을 처음에 생성했던 Pager 인스턴트 생성할 때 매개 변수로 담았습니다.

 

그 이유는 레코드 개수에 맞춰서 페이지를 나눠야 하기 때문에 매개 변수로 넣어줬고, 시작(start) , 끝(end) 처리도 해줘야 하기 때문에 Pager 파일에서 각 기능에 맞게 getter로 처리해 줍니다.

 

그럼 DAO에서 추가할 게 생겼기 때문에 처음에 게시물 목록 구현할 때 만들었던 메서드에start, end 변수를 매개 변수로 추가해서 요청합니다.


DAO

 

먼저 레코드 개수 처리했던 count 메서드 코드입니다.

 

 

count 메서드는 간단하게 mapper 파일에 요청하는 코드만 작성합니다.

다음은 list 메서드에 추가한 매개 변수 start, end 코드 작업을 합니다.

 

 

Map을 활용해서 한 곳에 담아서 mapper에 요청을 보냅니다.

 


board.xml(mapper)

 

DAO에서 각 메서드를 mapper에 연결해 주는 코드만 구현했습니다. 

그럼 각 메서드에 맞게 SQL문을 작성해서 처리를 해줍니다.

 

< count >

 

list는 이전에 작업했던 SQL문에서 수정해 줍니다.

 

< list >

mapper 작업이 끝났습니다. 

그럼 마지막으로 결과를 확인해 봅니다.

 


결과 출력

 

< 목록 페이지 >

 

 




마치며

 

오늘까지 게시물 기능 구현을 맞췄습니다.

다음 포스팅에서 뵙겠습니다.

728x90