우선 무엇을 변수로 가져오고 값을 리턴할지 배분하는게 어려웠다. 그래서 Mr.delbert님과 Jiho님의 도움으로 쿼리문을 아래와 같이 짜고, 변수를 아래와 같은 명하고 변수값을 어떻게 구할지 식을 계산했다.
# 입력값
pageNumber
totalCount
pageSize
listSize
총 페이지 값(매개변수)
총게시글수(매개변수)
10(고정값|노출되는 페이지수)
10(고정값| 한페이지당 노출되는 게시글수)
# 출력값
변수명
해를 구하는 식
underBar
(TotalCount / listSize ) + 1
현재 Page 게시글 start index
(pageNumber - 1)*10+1
현재 Page 게시글 last index
(pageNumber) * (listSize)
사실 위 표를 보는것보다 더 중요한게 스스로 아래와 같은 질문을 던지는게 코드를 짜는 사고력을 키우는데 유익하다. 그리고 mysql의 LIMIT와 OFFSET구문이 start인덱스와 last인덱스를 자동으로 db에서 추출해줘서 따로 스크립트단에서 값을 계산할 필요가 없다.
전체 페이징 숫자는 어떻게 구할까? -> (총게시글수) / (한페이지당 노출되는 게시글수)로 나누면돼
그럼만약 총게시글수는 31개일때 한페이지당 노출되는 게시글 수가 10개라면.. 페이지수가 3이 아니라 4가되어야 하지 않나?
만약 (총게시글수) / (한페이지당 노출되는 게시글수) = a 라고 가정하면, a < pageNumber(총페이지값)이면, last index값은 pageNumber값을 리턴해야 된다.
위 내용이 어렵다면? 아래 그림들을 참고하자:) Dbeaver를 활용해 한페이지당 출력되는 값을 Descending(큰숫자->작은숫자로 정렬)방법으로 시작인덱스에 맞춰 10개씩 출력되도록 쿼리를 실행시켜보았다. Desending 및 mariaDB query limit와 개념내용 아래링크 참고바란다. Assending은 반대개념인데, 작은숫자-> 큰숫자로 정렬하는 방법임. ex> 1, 2, 3, ...
0번째가 무엇을의미하나? 예를들면 총게시글이 108개인 경우 Desending방식으로 offset이 0이고, listSize가 10인 조건의 쿼리문을 실행시키면 아래 노란박스 부분만 출력됨을 알 수 있다.
제일 마지막 게시글항목번호(가장큰숫자)부터 10번째까지 차례대로 출력예시
그럼 만약 offset이 10부터라면? 무슨의미인가?
위에 엑셀그림처럼 98번째 게시글부터 89번째 게시글인덱스, 즉 11번째 인덱스부터 +10(=listSize)를 더한 20번째 인덱스까지 포함해서 리턴한다고 보면된다.
offset 10 인 쿼리문의 결과는? 현재 nvrg db에는 총27개의 게시글이 저장되어 있으므로 (27-10=17)번째 인덱스부터 쿼리실행결과값이 도출됨
결국, 유저가 게시물을 지속적으로 등록하기 때문에 총 게시글이 고정변수가 아니다. 시작인덱스값과 마지막인덱스값은 계속 변할 수 있다는 점 때문에 offset값으로 쿼리를 짜게됨을 깨달아야한다.
# list.jsp code 수정
<div class="pager">태그아래 아래와 같이 코드를 추가해주었다. 해당 코드는 위 내용을 포괄하여 paging처리를 해주는 조건문 및 변수들이다. 태그내에서 새롭게 선언한 변수들인 initSize와 underBar 변수는 앞서 본게시글 상단 입력출력값 해설표 참고바란다.
참고로 pageNumber나 totalCount는 이전에 짜놓은 ListDAO.java 클래스의 getCount()메소드나 ArrayList<Board> getList(int pageNumber) 메소드의 인자값에서 가져오는 변수값들이다.
# ListDAO.java 클래스의 getList() 메소드 code 수정
getNext()함수가 적용되지 않아, 특정 게시글을 삭제하면 해당 id의 listAvailable값은 0이되지만 list.jsp에선 그대로 게시글이 노출되는 예외가 발생했다. 예외처리를 위해 아래와 같이 쿼리를 수정해주었다. where절은 반드시 ORDER BY 또는 AND절 앞에 위치해야 한다. 안그러면 쿼리Syntax 에러가 뜬다.
public ArrayList<Board> getList(int pageNumber) {
String SQL = "SELECT * FROM LIST WHERE listAvailable = 1 ORDER BY listDate desc limit 10 offset ?";
ArrayList<Board> list = new ArrayList<Board>();
int offset = 0;
if (pageNumber > 1 )
{
offset = 10 * pageNumber - 10;
}
try {
PreparedStatement pstmt = conn.prepareStatement(SQL);
pstmt.setInt(1, offset);
rs =pstmt.executeQuery();
while ( rs.next()) {
Board text = new Board();
text.setListID(rs.getInt(1));
text.setListTitle(rs.getString(2));
text.setUserID(rs.getString(3));
text.setListDate(rs.getString(4));
text.setListContent(rs.getString(5));
text.setListAvailable(rs.getInt(6));
list.add(text);
}
} catch (Exception e) {
e.printStackTrace();
}
return list; //데이터베이스 오류
}
위코드를 ListDAO.jsp 파일에 추가수정해주면 아래와 같이 페이징 처리도 잘되고, 'Hi bluevulpe!'라는 지겨운ㅠㅠ ㅋㅋㅋㅋ 크로스 스크립트 알림창도 안뜨는 게시판 기능구현 성공~
list 첫번째 페이지 화면 예시
list 두번째 페이지 화면출력 예시
list 3번째 페이지 화면출력 예시
위 사진들 속 해당페이지 숫자들에 하이라이트마냥 빨간색표시가 되어있는것을 인지했는가?
# 페이징 숫자 하이라이트
<div class="pager">
<%
int listSize = 10;
int underBar = (totalCount / listSize) + 1;
for(int i = 1; i <= underBar; i++){
if(pageNumber == i){
out.println("<strong style='color: red;'>"+i+"</strong>");
}else {
out.println("<a href='/test/list.jsp?pageNumber="+i+"'>"+i+"</a>");
}
}
%>
</div>
현재 페이지 넘버가 i와 일치할때란? 결국 사용자가 선택한 페이지라고 이해하면 된다. 선택된 페이지는 하이퍼링크 처리는 안되며, 대신 red 로 하이라이트 색상처리를 해준다는 의미의 코드다.
빠른시일내로 '다음'과 '이전'버튼이 pageSize를 초과할때만 노출되고 구현되게끔 코드를 짜서 업데이트 하겠다. 여기까지 따라와주신 분들게 진심으로 감사드립니다:)
Copyright ⓒ 2021 by bluevulpe All Contents cannot be copied without permission.