고래씌

[JSP] 5-1. 게시판 만들기(페이지) 본문

Server/JSP과 Servlet

[JSP] 5-1. 게시판 만들기(페이지)

고래씌 2023. 12. 8. 10:50

1. 게시판 만들기

- SERVER 계정에 저장되어있는 게시판 테이블과 관련 테이블들을 보도록 하겠다.

BOARD 테이블

 

CATEGORY 테이블

 

ATTACHMENT 테이블

 

 

① 각 테이블에 관련한 클래스 생성하기

▶ Board 클래스는 Builder를 이용한다.

Builder는 메소드 순서가 안맞아도 필요한 값만 넣고 가져올수 있기 때문에 유용하므로 Builder를 사용한다!

 

■ Board 클래스

package com.kh.board.model.vo;

import java.sql.Date;

import oracle.net.aso.n;

public class Board {
//	BOARD_NO	NUMBER
	private int boardNo;

//	BOARD_TYPE	NUMBER
	private int boardType;

//	CATEGORY_NO	NUMBER
	private int categoryNo;

//	BOARD_TITLE	VARCHAR2(100 BYTE)
	private String boardTitle;

//	BOARD_CONTENT	VARCHAR2(4000 BYTE)
	private String boardContent;

//	BOARD_WRITER	NUMBER
	private String boardWriter;
	// 쿼리문으로 join시에는 회원번호를 활용하여 join할 것이고,
	// 조회결과 작성한 사용자의 이름 or id를 저장하기 위한 필드

//	COUNT	NUMBER
	private int count;

//	CREATE_DATE	DATE
	private Date createDate;

//	STATUS	VARCHAR2(1 BYTE)
	private String status;

	private String categoryName; // Board테이블에는 존재하지 않는 칼럼
	// DB에 Category 테이블에도 CATEGORY_NO가 있기 때문에 하나 생성 해둠

	public Board() {

	}

	public static class Builder {

		private int boardNo;
		private int boardType;
		private int categoryNo;
		private String boardTitle;
		private String boardContent;
		private String boardWriter;
		private int count;
		private Date createDate;
		private String status;
		private String categoryName; // Board테이블에는 존재하지 않는 칼럼

		public Board bulid() {
//			빌더에 초기화한 값을 그대로 Builder로 반환시켜줌

			// Board 타입 객체로 모두 옮겨놓음
			Board b = new Board();
			b.boardNo = boardNo;
			b.boardType = boardType;
			b.categoryNo = categoryNo;
			b.boardTitle = boardTitle;
			b.boardContent = boardContent;
			b.boardWriter = boardWriter;
			b.count = count;
			b.createDate = createDate;
			b.status = status;
			b.categoryName = categoryName;

			return b;
		}

		public Builder boardNo(int boardNo) {
			this.boardNo = boardNo;

			return this;
		}

		public Builder boardType(int boardType) {
			this.boardType = boardType;

			return this;
		}

		public Builder categoryNo(int categoryNo) {
			this.categoryNo = categoryNo;

			return this;
		}

		public Builder boardTitle(String boardTitle) {
			this.boardTitle = boardTitle;

			return this;
		}

		public Builder boardContent(String boardContent) {
			this.boardContent = boardContent;

			return this;
		}

		public Builder boardWriter(String boardWriter) {
			this.boardWriter = boardWriter;

			return this;
		}

		public Builder count(int count) {
			this.count = count;

			return this;
		}

		public Builder createDate(Date createDate) {
			this.createDate = createDate;

			return this;
		}

		public Builder status(String status) {
			this.status = status;

			return this;
		}

		public Builder categoryName(String categoryName) {
			this.categoryName = categoryName;

			return this;
		}
	}

//	 똑같이 한 이유는 /...?

	@Override
	public String toString() {
		return "Board [boardNo=" + boardNo + ", boardType=" + boardType + ", categoryNo=" + categoryNo + ", boardTitle="
				+ boardTitle + ", boardContent=" + boardContent + ", boardWriter=" + boardWriter + ", count=" + count
				+ ", createDate=" + createDate + ", status=" + status + ", categoryName=" + categoryName + "]";
	}

	public int getBoardNo() {
		return boardNo;
	}

	public void setBoardNo(int boardNo) {
		this.boardNo = boardNo;
	}

	public int getBoardType() {
		return boardType;
	}

	public void setBoardType(int boardType) {
		this.boardType = boardType;
	}

	public int getCategoryNo() {
		return categoryNo;
	}

	public void setCategoryNo(int categoryNo) {
		this.categoryNo = categoryNo;
	}

	public String getBoardTitle() {
		return boardTitle;
	}

	public void setBoardTitle(String boardTitle) {
		this.boardTitle = boardTitle;
	}

	public String getBoardContent() {
		return boardContent;
	}

	public void setBoardContent(String boardContent) {
		this.boardContent = boardContent;
	}

	public String getBoardWriter() {
		return boardWriter;
	}

	public void setBoardWriter(String boardWriter) {
		this.boardWriter = boardWriter;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public String getCategoryName() {
		return categoryName;
	}

	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}

}

 

 

■ Category 클래스

package com.kh.board.model.vo;

public class Category {
	
	private int categoryNo;
	private String categoryName;
	
	public Category() {
		
	}

	public Category(int categoryNo, String categoryName) {
		super();
		this.categoryNo = categoryNo;
		this.categoryName = categoryName;
	}

	public int getCategoryNo() {
		return categoryNo;
	}

	public void setCategoryNo(int categoryNo) {
		this.categoryNo = categoryNo;
	}

	public String getCategoryName() {
		return categoryName;
	}

	public void setCategoryName(String categoryName) {
		this.categoryName = categoryName;
	}

	@Override
	public String toString() {
		return "Category [categoryNo=" + categoryNo + ", categoryName=" + categoryName + "]";
	}
}

 

 

■ Attachment 클래스

package com.kh.board.model.vo;

import java.sql.Date;

public class Attachment {
//	FILE_NO	NUMBER
	private int fileNo;
//	REF_BNO	NUMBER
	private int refBno;
//	ORIGIN_NAME	VARCHAR2(255 BYTE)
	private String originName;
//	CHANGE_NAME	VARCHAR2(255 BYTE)
	private String changName;
//	FILE_PATH	VARCHAR2(1000 BYTE)
	private String filePath;
//	UPLOAD_DATE	DATE
	private Date uploadDate;
//	FILE_LEVEL	NUMBER
	private int fileLevel;
//	STATUS	VARCHAR2(1 BYTE)
	private String status;
	
	public Attachment() {
		
	}

	public Attachment(int fileNo, int refBno, String originName, String changName, String filePath, Date uploadDate,
			int fileLevel, String status) {
		super();
		this.fileNo = fileNo;
		this.refBno = refBno;
		this.originName = originName;
		this.changName = changName;
		this.filePath = filePath;
		this.uploadDate = uploadDate;
		this.fileLevel = fileLevel;
		this.status = status;
	}

	public int getFileNo() {
		return fileNo;
	}

	public void setFileNo(int fileNo) {
		this.fileNo = fileNo;
	}

	public int getRefBno() {
		return refBno;
	}

	public void setRefBno(int refBno) {
		this.refBno = refBno;
	}

	public String getOriginName() {
		return originName;
	}

	public void setOriginName(String originName) {
		this.originName = originName;
	}

	public String getChangName() {
		return changName;
	}

	public void setChangName(String changName) {
		this.changName = changName;
	}

	public String getFilePath() {
		return filePath;
	}

	public void setFilePath(String filePath) {
		this.filePath = filePath;
	}

	public Date getUploadDate() {
		return uploadDate;
	}

	public void setUploadDate(Date uploadDate) {
		this.uploadDate = uploadDate;
	}

	public int getFileLevel() {
		return fileLevel;
	}

	public void setFileLevel(int fileLevel) {
		this.fileLevel = fileLevel;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	@Override
	public String toString() {
		return "Attachment [fileNo=" + fileNo + ", refBno=" + refBno + ", originName=" + originName + ", changName="
				+ changName + ", filePath=" + filePath + ", uploadDate=" + uploadDate + ", fileLevel=" + fileLevel
				+ ", status=" + status + "]";
	}
}

 

 

▶ 공통적인 스타일을 주기위해 common.css 파일에 스타일 속성 추가

■ common.css 

/* 게시판 목록 시작 */
.list-area{
	border : 1px solid white;
	text-align : center;
}
.list-area>tbody>tr:hover{
	background: gray;
	cursor: point;
}
/* 게시판 목록 끝 */

 

 

▶ 사용자에게 보여지는 기본화면에 일반게시판 연결을 해주기 위해서 menubar.jsp 에 일반게시판 링크 연결

■ menubar.jsp

 

 

② 게시판을 가져오기위해 SQL 쿼리문 작성

■ board-mapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
	
	<entry key="selectList">
		SELECT *
		FROM(
			SELECT ROWNUM RNUM, A.*
			FROM(SELECT BOARD_NO,
				  CATEGORY_NAME,
				  BOARD_TITLE,
				  USER_ID,
				  COUNT,
				  CREATE_DATE
				FROM BOARD B
				LEFT JOIN CATEGORY USING(CATEGORY_NO)
				JOIN MEMBER ON (BOARD_WRITER = USER_NO)
				WHERE BOARD_TYPE = 1
				  AND B.STATUS = 'Y'   
				ORDER BY BOARD_NO DESC
				) A
				<-- STATUS = 'Y'이면서 BOARD_TYPE =1만 가져온다! --> 
		)
		WHERE RNUM BETWEEN ? AND ?   <-- 1페이지에서 ~ 몇페이지? --> 
	</entry>
	
	<entry key="selectListCount">
		SELECT COUNT(*)
		FROM BOARD
		WHERE STATUS = 'Y'
		  AND BOARD_TYPE = 1
	</entry>

</properties>

 

 

③ 서버로 전송할 수 있는 Servlet 생성

▶ maxPage (가장 마지막 페이지가 몇번 페이지인지(총 페이지 수))공식

=> listCount, boardLimit에 영향을 받음

- 공식 구하기
    단, boardLimit 10 이라는 가정하에 규칙을 세워봄


- 총 개수(listCount)     boardLimit           maxPage
 2000개        /         10개             200번 페이지
 2001개        /         10개             200.1번 페이지 => 올림처리 201번페이지
 2005개 -------------------------------> 200.5번 → 201번 페이지
 2010개        /         10개             201번 페이지
 2011개        /         10개             201.1번 페이지 => 올림처리 202번페이지
 => 나눗셈 연산한 결과를 올림처리한다면 maxPage 값이 나온다.
   

1) listCount를 double로 형변환
2) listCount / boardLimit
3) 결과에 올림처리후
4) 결과값을 int로 변환

 

 

▶ StartPage : 페이징바의 시작수

=> pageLimit, currentPage에 영향을 받음


- 공식 구하기
  단, pageLimit는 10이라는 가정하에 규칙을 세워보기.

  startPage : 1, 11, 21, 31, 41, .... n => n*10+1 이런식으로 증가한다!
   
  만약에 pageLimit가 5가 된다? 1, 6, 11, 16 ... => n*5+1 

  즉, n*pageLimit+1 의 공식으로 구하면 된다!
 
  currentPage(요청한 페이지)   |    startPage
         1                                                 1
         5                                                 1
       10                                                 1
        
       11                                                11
       15                                                11
       20                                                11
       

     1~10 => 1   => n*pageLimit + 1 ==>  n=0
    11~20 => 11  => n*pageLimit + 1 ==> n=1
    21~30 => 21  => n*pageLimit + 1 ==> n=2
    n = (currentPage - 1) / pageLimit
                0~9 / 10 = 0
             10~19 / 10 = 1
             20~29 / 10 = 2
   startPage = n * pageLimit + 1
   => (currentPage - 1) / pageLimit * pageLimit + 1

 

 

▶ endPage : 페이징바의 끝수

=> startPage, pageLimit에 영향을 받음 + maxPage에도

- 공식 구하기(pageLimit는 10이라는 가정)
 
 startPage : 1 => 끝수 : 10
 startPage : 11 => 20
 startPage : 21 => 30
 
 endPage = startPage + pageLimit - 1;

 

 

▶ endPage 를 maxPage 와 같도록 설정

if(endPage > maxPage) {
endPage = maxPage;   // 끝 페이지가 maxPage보다 많아지면 같도록 설정
}

 

 

▶ 이제 이 페이지 정보를 하나의 공간에 담아서 보내도록 설정

페이지 정보들을 담아주는 vo 클래스가 필요함. 

=> 사진 게시판, 공지사항게시판, 그외에 추가될 수 있는 게시판에서도 쓰일 것이므로 common 패키지에 만들기

// 1. 페이징바 만들때 필요한 객체
PageInfo pi = new PageInfo(listCount, currentPage, pageLimit,
boardLimit, maxPage, startPage, endPage);

// 2. 현재 사용자가 요청한 페이지에 보여질 게시글 리스트
ArrayList<Board> list = new BoardService().selectList(pi);

 

 

▶ 하나의 공간에 담아주는 vo 클래스는 PageInfo.java에서 처리

package com.kh.common.model.vo;

public class PageInfo {
	private int listCount;  // 총 게시글 개수
	private int currentPage;  // 현재 요청한 페이지
	private int pageLimit;   // 페이지바 하단에 보여질 페이징바의 페이지 최대 갯수
	private int boardLimit; // 한 페이지에 보여질 게시글의 최대 개수
	
	private int maxPage;  // 가장 마지막 페이지가 몇번 페이지인지(총 페이지수)
	private int startPage;  // 페이지 하단에 보여질 페이징바의 시작수
	private int endPage;  // 페이지 하단에 보여질 페이징바의 끝 수 
	
	public PageInfo(int listCount, int currentPage, int pageLimit, int boardLimit, int maxPage, int startPage,
			int endPage) {
		super();
		this.listCount = listCount;
		this.currentPage = currentPage;
		this.pageLimit = pageLimit;
		this.boardLimit = boardLimit;
		this.maxPage = maxPage;
		this.startPage = startPage;
		this.endPage = endPage;
	}

	public int getListCount() {
		return listCount;
	}

	public void setListCount(int listCount) {
		this.listCount = listCount;
	}

	public int getCurrentPage() {
		return currentPage;
	}

	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}

	public int getPageLimit() {
		return pageLimit;
	}

	public void setPageLimit(int pageLimit) {
		this.pageLimit = pageLimit;
	}

	public int getBoardLimit() {
		return boardLimit;
	}

	public void setBoardLimit(int boardLimit) {
		this.boardLimit = boardLimit;
	}

	public int getMaxPage() {
		return maxPage;
	}

	public void setMaxPage(int maxPage) {
		this.maxPage = maxPage;
	}

	public int getStartPage() {
		return startPage;
	}

	public void setStartPage(int startPage) {
		this.startPage = startPage;
	}

	public int getEndPage() {
		return endPage;
	}

	public void setEndPage(int endPage) {
		this.endPage = endPage;
	}

	@Override
	public String toString() {
		return "PageInfo [listCount=" + listCount + ", currentPage=" + currentPage + ", pageLimit=" + pageLimit
				+ ", boardLimit=" + boardLimit + ", maxPage=" + maxPage + ", startPage=" + startPage + ", endPage="
				+ endPage + "]";
	}

}

 

 

④ JDBCTemplate 클래스와 연결하여 연결 객체 생성하기(BoardService 클래스)

■ JDBCTemplate

package com.kh.common;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCTemplate {
	
	// 1. Connection 객체 생성 후 Connection을 반환하는 메소드
	public static Connection getConnection() {
		// Properties
		Properties prop = new Properties();  // 키, 밸류 형태로 문자열형태로 저장함
		
		// 읽어들이고자하는 driver.properties 파일의 물리적인 경로 제시
		String fileName = JDBCTemplate.class.getResource("/sql/driver/driver.properties").getPath();
		// 현재 경로의 절대경로로 driver.properties 파일을 찾는다.
		// C:\Web-workspace2\JSP_Project1\WebContent\WEB-INF\classes\sql\driver  => 이 위치를 찾는다
		
		try {
			prop.load(new FileInputStream(fileName));
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		Connection conn = null;
		
		// 1) jdbc driver 등록
		try {
			Class.forName(prop.getProperty("driver"));
			
			// 2) db와 접속된 Connection 객체 생성
			conn = DriverManager.getConnection(prop.getProperty("url"),
											prop.getProperty("username"),
											prop.getProperty("password"));
					
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		return conn;
		
	}
		
	//2. 전달받은 JDBC용 객체를 반납시켜주는 메소드(객체별로 오버로딩)
	//2_1) Connection객체를 전달받아서 반납시켜주는 메소드
	public static void close(Connection conn) {
		try {
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	//2_2) Statement객체를 전달받아서 반납시켜주는 메소드
	public static void close(Statement stmt) { // Statement + PreparedStatment 둘다
		// 매개변수로 전달 가능(다형성)
		try {
			stmt.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	//2_3) ResultSet 객체를 전달받아서 반납시켜주는 메소드(오버로딩)
	public static void close(ResultSet rset) {
		try {
			rset.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 3. 전달받은 Connection객체를 가지고 트랜잭션 처리를 해주는 메소드
	// 3_1.) Commit메소드
	public static void commit(Connection conn) {
		try {
			conn.commit();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	// 3_2) rollback메소드
	public static void rollback(Connection conn) {
		try {
			conn.rollback();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

}

 

 

■ BoardService.java 

 

package com.kh.board.model.service;

import static com.kh.common.JDBCTemplate.close;
import static com.kh.common.JDBCTemplate.getConnection;

import java.sql.Connection;
import java.util.ArrayList;

import com.kh.board.model.dao.BoardDao;
import com.kh.board.model.vo.Board;
import com.kh.common.model.vo.PageInfo;

public class BoardService {

	public int selectListCount() {
		
		Connection conn = getConnection();
		int listCount = new BoardDao().selectListCount(conn);
		close(conn);
		
		return listCount;
	}

	public ArrayList<Board> selectList(PageInfo pi) {
		
		Connection conn = getConnection();
		
		ArrayList<Board> list = new BoardDao().selectListCount(conn, pi);
		
		close(conn);
		
		return list;
	}

}

 

 

 

⑤ board-mapper.xml 파일에 SQL문을 작성했던 것을 처리하여 저장

■ BoardDao.java

package com.kh.board.model.dao;

import static com.kh.common.JDBCTemplate.close;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Properties;

import com.kh.board.model.vo.Board;
import com.kh.common.model.vo.PageInfo;

public class BoardDao {
	
	private Properties prop = new Properties();
	
	// Hashtable은 키와 값을 (Object, Object)의 형태로 저장하는데 비해 
	// Properties는 (String, String)형태로 저장하는 보다 단순화된 컬렉션 클래스이다.
	// 주로 애플리케이션의 환경설정과 관련된 속성을 저장하는데 사용되며
	// 데이터를 파일로부터 읽고 쓰는 편리한 기능을 제공한다.
	// 그래서 간단한 입출력은 Properties를 활용하면 몇 줄의 코드로 쉽게 해결할 수 있다.
	
	public BoardDao() {
		try {
			prop.loadFromXML(new FileInputStream(
					BoardDao.class.getResource("/sql/board/board-mapper.xml").getPath()));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

 

 

⑥ SQL 쿼리문 실행

■ BoarderDao.java

public ArrayList<Board> selectListCount(Connection conn, PageInfo pi) {
		// SELECT 문 => ResultSet
		ArrayList<Board> list = new ArrayList<>();
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		String sql = prop.getProperty("selectList");
		
		try {
			pstmt = conn.prepareStatement(sql);
			
			/*
			 * boardLimit = 10
			 * currentPage = 1 => 1~10   사용자가 요청한 페이지가 1페이지면 1~10페이지를 보여줌
			 * currentPage = 3 => 21~30
			 * 
			 * 시작값 = (currentPage -1) * boardLimit + 1
			 * 끝값 = 시작값 + boardLimit - 1
			 */
			
			int startRow = (pi.getCurrentPage() - 1) * pi.getBoardLimit() + 1;
			int endRow = startRow + pi.getBoardLimit() - 1;
			
			pstmt.setInt(1, startRow);
			pstmt.setInt(2, endRow);
			
			
			rset = pstmt.executeQuery();
			
			while(rset.next()) {
				Board b = new Board.Builder().boardNo(rset.getInt("BOARD_NO"))
											 .categoryName(rset.getString("CATEGORY_NAME"))
											 .boardTitle(rset.getString("BOARD_TITLE"))
											 .boardWriter(rset.getString("USER_ID"))
											 .count(rset.getInt("COUNT"))
											 .createDate(rset.getDate("CREATE_DATE"))
											 .Bulid();  // build 객체 반환
				list.add(b);   // 생성한 Board 객체 b를 list에 추가
			}
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			close(rset);
			close(pstmt);
		}
		
		return list;
	}

 

 

 

⑦ 사용자에게 보여질 화면 디자인

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="com.kh.common.model.vo.PageInfo, java.util.ArrayList, com.kh.board.model.vo.Board" %>
<% 
	PageInfo pi = (PageInfo) request.getAttribute("pi");  // BoardListController 에서 pi를 받아오고,
	ArrayList<Board> list = (ArrayList<Board>) request.getAttribute("list"); // BoardListController에서 Board객체 자료형인 list 받아옴
	
	int startPage = pi.getStartPage();
	int endPage = pi.getEndPage();
	int currentPage = pi.getCurrentPage();  // 사용자가 요청한 페이지 정보
	int maxPage = pi.getMaxPage();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<%@ include file="../common/menubar.jsp" %>
	
	<div class="outer">
		<br>
		<h2 align="center">일반게시판</h2>
		<br>
		
		<!-- 로그인한 회원만 글작성 버튼이 보이게 조정 -->
		<% if(loginUser != null){ %>
			<div align="right" style="width:850px;">
				<a href="<%=contextPath %>/insert.bo" class="btn btn-secondary">글작성</a>
				<br>
				<br>
		<% } %>
		
		<table align="center" class="list-area">
			<thead>
				<tr>
					<th width="70">글번호</th>
					<th width="70">카테고리</th>
					<th width="300">제목</th>
					<th width="100">작성자</th>
					<th width="50">조회수</th>
					<th width="100">작성일</th>
				</tr>
			</thead>
			<tbody>
				<% if(list.isEmpty()) { %>
					<tr>
						<td colspan="6">조회된 리스트가 없습니다..</td>
					</tr>
				<% }else { %>
					<% for(Board b : list) { %>
						<tr>
							<td><%= b.getBoardNo() %></td>
							<td><%= b.getCategoryName() %></td>
							<td><%= b.getBoardTitle() %></td>
							<td><%= b.getBoardWriter() %></td>
							<td><%= b.getCount() %></td>
							<td><%= b.getCreateDate() %></td>
						</tr>
					<% } %>
				<% } %>
			</tbody>
		</table>
		
		<br><br>
		
		<!-- 페이징바 -->
		
		<div align="center" class="paging-area">
			<% if(currentPage != 1){ %>
				<button onclick="location.href= '<%= contextPath %>/list.bo?currentPage=<%=currentPage -1 %>'">&lt;</button>
			<% } %>
			
			<% for(int p = startPage; p <= endPage; p++) { %>
				
				<% if(p != currentPage) { %>
					<button onclick="location.href= '<%= contextPath %>/list.bo?currentPage=<%=p%>'"><%= p %></button>
					<!-- 절대경로로 보내고 있음  -->
				<% } else { %>
					<button disabled><%= p %></button>
			
				<% } %>
			<% } %>
			
			<% if(currentPage != maxPage) { %>
				<button onclick="location.href= '<%= contextPath %>/list.bo?currentPage=<%=currentPage + 1 %>'">&gt;</button>
			<% } %>
		</div>
		
	</div>

</body>
</html>