웹 애플리케이션 게시판 페이징처리

학습하며 개인적으로 필요했던 부분만 메모하였습니다. 화면쪽 View 부분은 생략하였습니다.

페이징처리시 필요한 파라미터

  • 현재 페이지번호 (pageNo)

  • 한 페이지당 보여줄 데이터 수 (amount)

  • 이전, 다음 (prev, next)

  • 시작 번호와 끝 번호 (Start, End)

  • 총 게시물 개수 (total)

순서

  1. 시작페이지, 페이지당 게시물 개수에 대한 클래스 생성

  2. mapper or DAO 설정

  3. mapper.xml 쿼리 작성

  4. Controller, Service 설정

  5. 시작, 끝 페이지 및 이전, 다음에 대한 PageDTO 클래스 생성

  6. 총 게시물 개수 (total) 설정

1. 시작페이지, 페이지당 게시물 개수에 대한 클래스 생성

게시판 페이지처리를 위해선 시작페이지와 한 페이지에 몇개의 게시물을 보여줄지 지정을 해야합니다.

해당 기준을 잡기 위한 Criteria 클래스를 생성합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@Getter
@Setter
@ToString
public class Criteria {
private int pageNum;
private int amount;

//기본 생성자 기본값 1페이지, 10개
public Criteria () {
this(1,10);
}

public Criteria (int pageNum, int amount) {
this.pageNum=pageNum;
this.amount=amount;
}

}
  • 기본 생성자와 매개변수가 있는 생성자를 가진 객체를 생성합니다.

    • 기본값은 시작 1페이지, 한 페이지당 10개씩 보여주는 기본 생성자

2. mapper or DAO 설정

  • BoardMapper(DAO를 Interface Mapper로 처리) 설정
1
2
3
4
5
public interface BoardMapper {

public List<BoardDTO> getListPaging(Criteria cri);

}

3. mapper.xml 쿼리 작성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<select id="getListPaging" resultType="org.zerock.domain.BoardDTO">
<![CDATA[
	select bno, title, content, writer, regdate, updatedate from
	(
    	select /*+ INDEX_DESC (tbl_board pk_board) */
		rownum no, bno, title, content, writer, regdate, updatedate 
		from
		tbl_board 
		where rownum <= #{pageNum} * #{amount}
	) where no > (#{pageNum} - 1) * #{amount}
]]>
</select>
  • 성능을 위해 order by 대신 hint Index를 사용하였습니다.

    • 참고 - oracle hint 정리

    • ex : pageNum = 1 , amount = 10 -> where rownum <= 10

      • desc(최신)으로 정렬순으로 1 ~ 10까지 rownum의 10개 게시물을 확인할 수 있습니다.
    • ex : pageNum = 2 , amount = 10 -> where rownum <= 20

      • rownum이 20과 같거나 작고(20까지 포함) no > (#{pageNum} - 1) * #{amount} 는 rownum이 10보다 크다.

        • 11 ~ 20까지 게시물

4. Controller, Service 설정

  • BoardService 수정
1
2
3
public interface BoardService {
	public List<BoardDTO> getList(Criteria cri);
}	
  • BoardServiceImpl 수정
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@Log4j
@Service
@AllArgsConstructor
public class BoardServiceImpl implements BoardService{

private BoardMapper mapper;

  @Override
	public List<BoardDTO> getList(Criteria cri) {
		log.info("getList..."+cri);
		return mapper.getListPaging(cri);
	}
  • BoardController 수정
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor
public class BoardController {
	
	private BoardService service;
	
	@GetMapping("/list")
	public void list(Model model, Criteria cri) {
		log.info("list" + cri);
		model.addAttribute("list",service.getList(cri));
	}

5. 시작, 끝 페이지 및 이전, 다음에 대한 PageDTO 클래스 생성

  • 페이지 끝 번호

    • (int)(Math.ceil(페이지 번호 / 10.0)) * 10)
  • 페이지 시작 번호

    • 끝 번호 - 9
  • Real종료 페이지

    • (int)(Math.ceil((total * 1.0) / amount))

      • real종료 < 끝페이지일때 사용
  • 이전, 다음

    • 이전 - 시작페이지 > 1

    • 다음 - 종료페이지 < Real종료페이지

위에 규칙을 통해 클래스를 설계합니다.

  • PageDTO
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Getter
@ToString
public class PageDTO {
	
	private int startPage;
	private int endPage;
	private boolean prev, next;
	private int total;
	//페이지 번호(pageNum), 데이터수(amount)
	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;
		
		//보여줄 페이지가 10개 단위가 아닐 시 끝페이지 번호 처리 
		int realEnd = (int) (Math.ceil((total * 1.0) / cri.getAmount()));
		if(realEnd<this.endPage) {
			this.endPage = realEnd;
		}
		
		this.prev = this.startPage > 1;
		this.next = this.endPage < realEnd;
		
	}
}

6. 총 게시물 개수 (total)

  • Mapper Interface에 새로운 함수 getTotalCount를 추가합니다.

    • Criteria 객체를 매개변수로 지정 -> 검색 활용
1
2
3
4
5
public interface BoardMapper {
	public List<BoardDTO> getListPaging(Criteria cri);

	public int getTotalCount(Criteria cri);
}
  • Mapper.xml 쿼리 작성
1
2
3
<select id="getTotalCount" resultType="int">
	select count(*) from tbl_board where bno > 0
</select>
  • BoardService 및 ServiceImpl
1
2
3
4
5
6
7
8
9
//Service 클래스
public int getTotal(Criteria cri);

//ServiceImpl 클래스
@Override
public int getTotal(Criteria cri) {
  log.info("getTotal : "+cri);
  return mapper.getTotalCount(cri);
}
  • BoardController 작성
1
2
3
4
5
6
7
8
9
@GetMapping("/list")
public void list(Model model, Criteria cri) {
    log.info("list" + cri);
    model.addAttribute("list",service.getList(cri));
    //전체 게시물 수
    int total = service.getTotal(cri);
    log.info("total : "+total);
    model.addAttribute("pageMaker",new PageDTO(cri,total));
}


Reference