Notice
Recent Posts
Recent Comments
관리 메뉴

Developer Gonie

[9주차] 29. {게시판} 게시글 보여주는 기능(list.jsp) 본문

K-DigitalTraining 강의/8. JSP

[9주차] 29. {게시판} 게시글 보여주는 기능(list.jsp)

이대곤 2022. 7. 21. 19:35

list.jsp에서 구현해야할 사항

첫번째
사용자가 요청(클릭)한 페이지 번호를 넘겨받아 이에 해당하는 게시글들을 pageSize 개수만큼 보여준다.

 

두번째
하단에는 다른 페이지로 넘어갈 수 있도록 페이지 번호를 보여준다.

첫번째 사항 구현하기

사용자가 페이지 번호를 클릭하면 페이지 번호를 넘겨받아 해당 페이지를 보여주면 되는데,

맨 처음에는 사용자가 페이지 번호를 클릭해서 list.jsp를 접근하는게 아니기 때문에

pageNum 값을 열어봐서 null 이면 1페이지를 보여줘야 하는구나를 알도록 해줘야 한다.

그리고 한 줄로 표현할 수 있는 부분을 굳이 두 줄로 나눠 작성한 이유는

pageNum이 null인 경우 Integer.parseInt() 연산을 시도하려고 하면 에러가 나기 때문에 이렇게 구현한 것임.

String pageNum = request.getParameter("pageNum");
	if(pageNum == null){ 
		pageNum = "1"; // 맨 처음엔 첫번째 페이지가보여지므로 
	}
int currentPage = Integer.parseInt(pageNum);

그 다음 한 페이지에 최대 몇개의 글을 보여줄지에 대한 값을 가지는 변수를 만들어야 한다.

int pageSize = 10;

그 다음 수 많은 글들 중 현재 페이지에서는 몇번부터 몇번까지의 글을 보여줘야하는지를 구해놓는 부분이 있어야한다.

그래야 DB에서 해당 레코드들을 가져와 띄워줄 수 있지 않겠는가?

startRow, endRow는 테이블에서 num column의 값이 아니라

최신순, 가족순, 답답글 순으로 정렬하고 rank column의 값에 조건을 걸기 위한 값이라는 것을 알아야 함.

currentPage가 1이고, pageSize가 10 이라는 가정하에 startRow, endRow 는 각각 1, 10의 값을 가짐

currentPage가 2이고, pageSize가 10 이라는 가정하에 startRow, endRow 는 각각 11, 20의 값을 가짐

int startRow = (currentPage-1) * pageSize + 1;
int endRow = currentPage * pageSize;

그다음 DAO객체를 생성해서 전체 레코드의 개수를 가져와야 하는데 그 이유는 레코드가 존재하지 않을시 게시물이 존재하지 않는다는 화면을 보여주고, 0개가 아닐시 위에서 구한 startRow, endRow 값을 가지고 DB에서 이 사이의 rank 값을 가지는 것들만 select 쿼리문으로 요청하여 가져와 테이블 형태로 보여주기 위함임.

//DAO 객체 생성
BoardDao dao = BoardDao.getInstance();
	
//DAO 객체를 이용해 레코드의 모든 개수를 가져옴
int countAll = dao.getArticleCount(); // 레코드의 전체 개수를 가져옴, 전체 갯수를 알아야 필요한 페이지 번호를 알 수 있음
	
//DAO 객체를 이용해 현재 페이지에 보여줄 레코드만 가져옴
ArrayList<BoardBean> list = null;
if(countAll > 0){
	list = dao.getArticles(startRow, endRow);
}

가져온 레코드들은 num 값을 가지고 있는데 이것은 DB에 삽입된 순서 값이라서 이를 그대로 보여주면 산만해 보인다.
따라서, 원래 각 row가 가지고 있는 num 값은 사용자에게 보여주지 않고, 대신 아래의 변수를 이용하여 num 값과 무관하게 제일 큰 값부터 하나씩 줄여나간 수를 앞에 보여주기 위한 변수를 둔다.  

//맨 앞의 열에 오는 숫자를 1씩 줄여주며 보여주기 위한 숫자 변수
int number = countAll - (currentPage - 1) * pageSize;

이제는 가져온 데이터를 테이블 형태로 출력해주면 되는데,

먼저 열 이름을 출력해주고 만약 존재하는 게시글이 없다면 게시글이 존재하지 않는다고 보여지도록 함

<table border="1" width="700">
	<caption><b>글목록(전체 글:<%=countAll %>)</b></caption>
	<tr>
		<td align = "right" bgcolor="<%=value_c %>">
			<a href="writeFrom.jsp">글쓰기</a>
		</td>
	</tr>
</table>

<table border="1" width="700">
	<tr bgcolor="<%=value_c%>">
		<td align="center">번호</td>
		<td align="center">제목</td>
		<td align="center">작성자</td>
		<td align="center">작성일</td>
		<td align="center">조회</td>
		<td align="center">IP</td>
	</tr>
	<%
	if (countAll == 0) {
	%>
	<tr>
		<td align="center" colspan="6">게시글이 없습니다.</td>
	</tr>
	<%
	}
	else{
    	...
        ...
	%>
</table>

게시글이 존재한다면 위의 else 부분에서 아래와 같이 테이블 형태로 출력.

다만, 답글인 경우 답글, 답답글, 답답답글 별로 각각의 앞에 공백의 크기를 다르게 해주어 계단식으로 보여지게 함.

그리고, 게시글을 보여줄 때 3가지 값을 같이 넘겨주는데

1) 특정 게시글이 눌렸을 때 어떤 게시글을 선택되었는지 식별하여 해당 게시물이 띄워지도록 num을 넘겨주며

2) 특정 게시글을 눌렀다가 목록보기를 눌렀을 때, 보던 페이지가 다시 보여질 수 있게 하기 위해 현재 pageNum을 넘겨주며
3) 마지막 페이지에서 하나 남은 특정 게시물이 삭제되었을 때, 보던 페이지 바로 전 페이지를 계산하기 위해 pageSize도 넘겨준다.

else{
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 날짜에 형식을 지정하는 클래스
		
	for (int i = 0; i < list.size(); i++) {
		BoardBean bean = list.get(i);
	%>
	<tr>
		<td align="center"><%=number-- %></td> <!-- 중구난방으로 나오는 num값 대신에 그냥 하나씩 감소하는 숫자가 보여지도록 함 -->
		<td>
		<%  //이 레코드가 원글이 아닌 답글인 경우에만 앞에 공백 이미지, re 사진을 넣어 계단식으로 보여지도록 함
			if(bean.getRe_level() > 0){ 
				int width = bean.getRe_level()*20; // 1->20, 2->40, 3-> 60
			%> 
				<!-- 답글인 경우 답글, 답답글, 답답답글 별로 각각 앞의 공백을 다르게줌 계단식으로 보이게 --> 
				<img src="./images/level.gif" width="<%=width %>" height="15">
					
				<!-- 답글의 경우 게시글의 제목 앞에 Re사진을 띄움  -->
				<img src="./images/re.gif" height="15"> 
			<%
			}//if문
			%>
			<!-- 글보기로 넘어갔다가 다시 글목록보기로 돌아올 때, 보던 페이지를 보여주려고 pageNum도 보냄 --> 
			<a href="content.jsp?num=<%=bean.getNum()%>&pageNum=<%=pageNum%>&pageSize=<%=pageSize%>"><%=bean.getSubject() %></a>
			<%
			if(bean.getReadcount() >= 10){ 
			%> 
				<img src="images/hot.gif" height="15" /> 
			<%
			}
		%>
		</td>
		<td align="center"><%=bean.getWriter() %></td>
		<td align="center"><%=sdf.format(bean.getReg_date()) %></td>
		<td align="center"><%=bean.getReadcount() %></td>
		<td align="center"><%=bean.getIp() %></td>
	</tr>
	<%
	}//for
}//else

두번째 사항 구현하기

첫번째 사항을 구현하며 만든 currentPage, pageSize, countAll 변수들을 이용하여 아래 사항을 구현

<% /* 하단에 페이지번호들을 출력하는 코드 */
if(countAll > 0){
	//한 번에 보여줄 페이지의 개수
	int pageBlock = 10;
		
	// currentPage 1~10페이지에서는 startPage, endPage 는 각각 1, 10
	// currentPage 11~20페이지에서는 startPage, endPage 는 각각 11, 20
	int startPage = (int)((currentPage - 1)/pageBlock) * pageBlock + 1; 
	int endPage = startPage + pageBlock - 1;
		
	//필요한 전체 페이지 개수(바로 아래서 필요함)
	int pageCount = (int)(countAll / pageSize) + (countAll%pageSize == 0 ? 0 : 1); // ex) 245개의 레코드가 있다면 25개의 페이지가 필요
	
	//11~20페이지가 아니라 보여줄게 끝나 16페이지 까지만 필요한 경우도 있을 것이므로
	if(endPage > pageCount){
		endPage = pageCount;
	}
	
	if(startPage > pageBlock){
	%>	<a href="list.jsp?pageNum=<%=startPage-10 %>">[이전]</a> <%	
	}//if
		
	for(int i=startPage; i<=endPage; i++){
	%>	<a href="list.jsp?pageNum=<%=i%>">[<%=i%>]</a> <%
	}//for
	
	if(endPage < pageCount){
	%>	<a href="list.jsp?pageNum=<%=startPage+10 %>">[다음]</a> <%
	}
}
%>

첫번째 사항 구현하며 사용한 DB관련 함수 살펴보기

 

 

전체 코드

<%@page import="java.text.SimpleDateFormat"%>
<%@page import="board.BoardBean"%>
<%@page import="java.util.ArrayList"%>
<%@page import="java.sql.PreparedStatement"%>
<%@page import="java.sql.Connection"%>
<%@page import="board.BoardDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ include file="color.jsp" %> <!-- 코드 이어붙이는 include 액션태그 -->

<style>
	body{
		text-align: center; /* body태그는 없지만  */
	}

	table{
		margin : auto; /* 테이블 요소 가운데 정렬 */
	}
</style>

list.jsp<br>

<%
	//사용자가 하단에 있는 페이지 번호(<a>요소)중 하나를 클릭하면 넘겨받는 파라미터로 몇번째 페이지를 띄울 것인지 알기
	//맨 처음 접속시 이 변수에 넘어오는 값이 없을 것이므로 null이 반환되면 1페이지로 인식 
	String pageNum = request.getParameter("pageNum");
	if(pageNum == null){ 
		pageNum = "1"; // 맨 처음엔 첫번째 페이지가보여지므로 
	}
	int currentPage = Integer.parseInt(pageNum);

	//한 페이지에 보여질 레코드 개수
	int pageSize = 10;
	
	//currentPage에 따라 DB에서 가져올 행의 시작번호, 끝번호를 계산하는 공식(이 값은 num 컬럼의 값이 아니라 rank로 필터링 할 때 사용됨)
	//currentPage=1 페이지라면 startRow의 값이랑 endRow의 값은 각각 1, 10 
	//currentPage=2 페이지라면 startRow의 값이랑 endRow의 값은 각각 11, 20 	
	int startRow = (currentPage-1) * pageSize + 1;
	int endRow = currentPage * pageSize;	
	
	//DAO 객체 생성
	BoardDao dao = BoardDao.getInstance();
	
	//DAO 객체를 이용해 레코드의 모든 개수를 가져옴
	int countAll = dao.getArticleCount(); // 레코드의 전체 개수를 가져옴, 전체 갯수를 알아야 필요한 페이지 번호를 알 수 있음
	
	//DAO 객체를 이용해 현재 페이지에 보여줄 레코드만 가져옴
	ArrayList<BoardBean> list = null;
	if(countAll > 0){
		list = dao.getArticles(startRow, endRow);
	}
	
	//아래서 그냥 맨 앞의 열에 오는 숫자를 1씩 줄여주며 보여주기 위한 숫자 변수
	int number = countAll - (currentPage - 1) * pageSize;
%>

	
<table border="1" width="700">
	<caption><b>글목록(전체 글:<%=countAll %>)</b></caption>
	<tr>
		<td align = "right" bgcolor="<%=value_c %>">
			<a href="writeFrom.jsp">글쓰기</a>
		</td>
	</tr>
</table>

<table border="1" width="700">
	<tr bgcolor="<%=value_c%>">
		<td align="center">번호</td>
		<td align="center">제목</td>
		<td align="center">작성자</td>
		<td align="center">작성일</td>
		<td align="center">조회</td>
		<td align="center">IP</td>
	</tr>
	<%
	if (countAll == 0) {
	%>
	<tr>
		<td align="center" colspan="6">게시글이 없습니다.</td>
	</tr>
	<%
	}
	else{
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); // 날짜에 형식을 지정하는 클래스
		
		for (int i = 0; i < list.size(); i++) {
			BoardBean bean = list.get(i);
		%>
		<tr>
			<td align="center"><%=number-- %></td> <!-- 중구난방으로 나오는 num값 대신에 그냥 하나씩 감소하는 숫자가 보여지도록 함 -->
			<td>
			<%  //이 레코드가 원글이 아닌 답글인 경우에만 앞에 공백 이미지, re 사진을 넣어 계단식으로 보여지도록 함
				if(bean.getRe_level() > 0){ 
					int width = bean.getRe_level()*20; // 1->20, 2->40, 3-> 60
				%> 
					<!-- 답글인 경우 답글, 답답글, 답답답글 별로 각각 앞의 공백을 다르게줌 계단식으로 보이게 --> 
					<img src="./images/level.gif" width="<%=width %>" height="15">
						
					<!-- 답글의 경우 게시글의 제목 앞에 Re사진을 띄움  -->
					<img src="./images/re.gif" height="15"> 
				<%
				}//if문
				%>
				<!-- 글보기로 넘어갔다가 다시 글목록보기로 돌아올 때, 보던 페이지를 보여주려고 pageNum도 보냄 --> 
				<a href="content.jsp?num=<%=bean.getNum()%>&pageNum=<%=pageNum%>&pageSize=<%=pageSize%>"><%=bean.getSubject() %></a>
				<%
				if(bean.getReadcount() >= 10){ 
				%> 
					<img src="images/hot.gif" height="15" /> 
				<%
				}
			%>
			</td>
			<td align="center"><%=bean.getWriter() %></td>
			<td align="center"><%=sdf.format(bean.getReg_date()) %></td>
			<td align="center"><%=bean.getReadcount() %></td>
			<td align="center"><%=bean.getIp() %></td>
		</tr>
		<%
		}//for
	}//else
%>
</table>

<% /* 하단에 페이지번호들을 출력하는 코드 */
if(countAll > 0){
	//한 번에 보여줄 페이지의 개수
	int pageBlock = 10;
		
	// currentPage 1~10페이지에서는 startPage, endPage 는 각각 1, 10
	// currentPage 11~20페이지에서는 startPage, endPage 는 각각 11, 20
	int startPage = (int)((currentPage - 1)/pageBlock) * pageBlock + 1; 
	int endPage = startPage + pageBlock - 1;
		
	//필요한 전체 페이지 개수(바로 아래서 필요함)
	int pageCount = (int)(countAll / pageSize) + (countAll%pageSize == 0 ? 0 : 1); // ex) 245개의 레코드가 있다면 25개의 페이지가 필요
	
	//11~20페이지가 아니라 보여줄게 끝나 16페이지 까지만 필요한 경우도 있을 것이므로
	if(endPage > pageCount){
		endPage = pageCount;
	}
	
	if(startPage > pageBlock){
	%>	<a href="list.jsp?pageNum=<%=startPage-10 %>">[이전]</a> <%	
	}//if
		
	for(int i=startPage; i<=endPage; i++){
	%>	<a href="list.jsp?pageNum=<%=i%>">[<%=i%>]</a> <%
	}//for
	
	if(endPage < pageCount){
	%>	<a href="list.jsp?pageNum=<%=startPage+10 %>">[다음]</a> <%
	}
}
%>

 

 

Comments