스프링으로 게시판 만들어 보기 ( 게시판 페이징, 추천 프로시저 )

2019. 8. 9. 21:58개발공부/spring

게시판 목록 불러오기

가장 먼저 게시판 페이지에 핵심인 게시판 목록을 불러오는 작업입니다.

마이 바티스 동적 쿼리를 이용해서 검색 기능과 페이징 기능을 공부할 수 있습니다.

 

<select id="selectBoardList" parameterType="Criteria" resultType="BoardVO">
	select
    	*
	from
		(select 
			rownum rno,t.* 
		from 
			(select 
				s.*,(select member_id from springmember where member_no = s.member_no) member_id 
			from 
				springboard s 
			where 
				board_isshow != 'N' 
			order by 
				board_date desc) t
		      
              	<include refid="cri"></include>
		            
		     )
	where
		rno between (#{pageNum}-1)*#{amount}+1 and #{pageNum}*#{amount}
</select>

<sql id="cri">
	<if test="searchType != null">
		<choose>
			<when test='searchType == "T"'>
				and board_title like '%${searchText}%'
			</when>
			<when test='searchType == "C"'>
				and board_content like '%${searchText}%'
			</when>
			<when test='searchType == "W"'>
				 and member_id like '%${searchText}%'
			</when>
			<when test='searchType == "TC"'>
				and (board_title like '%${searchText}%' or board_content = '%${searchText}%')
			</when>
		</choose>
	</if>
</sql>

searchType 은 검색 옵션입니다. ( T 제목, C 내용, W 작성자 , TC 제목+내용 )

searchText는 검색어입니다.

pageNum 은 요청 페이지입니다.

amount는 게시글 조회 양입니다.

총 게시글수를 구하는 쿼리문에 choose부분을 다시 사용하기 위해서 재사용을 위해서 include로 사용했습니다.

 

 

** 게시판 페이징 원리 **

게시판 페이징이란 페이지를 전부 만드는 것이 아닙니다.

주요 목적은 현재 보고 있는 페이지를 기억하고 다음 페이지를 요청할 수 있도록 해주는 게 목적입니다.

변수에 현재 페이지를 기억해두었다가 다음 페이지를 호출할 때 플러스 1을 해도 되지만.....

기억을 하는 건 하는 거지만 기왕 하는 거 이쁘게 보이는 게 이용자 입장에서도 편리할 것입니다.

 

페이지를 표시하는 방법에는 여러 가지 방법이 있겠지만

그중 가장 많은 사이트가 사용하는 방법인 각각 10개의 페이지씩 나누어서 한 개 화면으로 보이게 만들어보았습니다.

처음 게시판에 접근을 한다면 당연히 1번 페이지를 보여주어야 합니다.

( 편의상 위 그림과 같이 한 묶음?을 화면이라고 표현하겠습니다. )

게시글이 총 1202 개가 있다고 하면 10개씩 나눈다면 120개의 화면과 2개만 있는 마지막 화면까지 총 121개의 화면이 생기는 원리입니다.

1,2,3,... ,8,9,10 ( 화면 1)

10,11,12,... ,18,19,20 (화면 2)

 

지금부터 작업해야 할 일은 만약 14페이지를 보고 있다면

위 그림과 같은 화면을 만들어 주면 됩니다.

 

데이터베이스에서 게시글 목록을 불러왔다면

요청 페이지 번호를 확인해서 14번이면 

 

1페이지가 아니라면 가장 앞으로(1페이지로) 버튼과 이전 페이지 (현재 페이지 - 1)

시작번호 11

현재 페이지 표시

끝번호 20

다음 페이지가 있다면 다음 페이지(현재 페이지 + 1) 버튼과 가장 뒤 페이지로 버튼을 추가해주어야 합니다.

@Data
public class PageInfo {
	// 보고있는 페이지에서 시작번호 ( 예) 10개씩이라고하면 1 , 11 , 21 , 31 ..... )
	private int startPage;
	
	// 보고있는 페이지에서 끝번호 ( 예) 10개씩이라고하면 10, 20, 30 ,40 ,50 .....)
	private int endPage;
	
	// 이번페이지가 있는지 다음페이지가 있는지 확인
	private boolean prev, next;
	
	// 가장 끝 페이지
	private int lastPage;
	
	// 전체 게시글 수
	private int total;
	
	// 요청이 온 페이지의 페이지번호와 몇개씩 보고 싶은지
	private Criteria cri;

	public PageInfo(Criteria cri) {
	      this.cri = cri;
	      this.total = cri.getTotalBoard();
	      
	      this.endPage = (int) (Math.ceil(cri.getPageNum() / 10.0))*10;
	      this.startPage = this.endPage - 9;
	      
	      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;
	}
}

 Math.ceil함수는 소수점 첫째 자리에서 올림 해주는 함수입니다.

주의해야 할 점은 총 1224 개의 게시글이 있고 1222번 페이지를 요청했다면 

1222/10.0 = 122.2

122.2 -> 123

123*10 = 1230

1230이 endPage가 되고

1230-9 = 1221 이 startPage가 됩니다.

시작번호는 맞지만 종료 페이지는 1224이어야 합니다.

때문에

int realEnd = (int) (Math.ceil((total*1.0)/cri.getAmount())); 
       
if(realEnd < this.endPage) { 
    this.endPage = realEnd; 
}

과정으로 한번 더 확인했습니다.

 

페이지 정보를 가지고 View 만들기

<div class="w3-bar pagingBox">
	<c:if test="${pagingInfo.prev}">
		<a onclick="getPage(1);" class="w3-button">««</a>
		<a onclick="getPage(${pagingInfo.cri.pageNum - 1});" href="#" class="w3-button">«</a>
	</c:if>
	<c:forEach var="i" begin="${pagingInfo.startPage}" end="${pagingInfo.endPage }">
		<c:choose>
			<c:when test="${i == pagingInfo.cri.pageNum }">
				<a onclick="getPage(${i});" class="w3-button w3-green">${i}</a>
			</c:when>
			<c:otherwise>
				<a onclick="getPage(${i});" class="w3-button">${i}</a>
			</c:otherwise>
		</c:choose>
	</c:forEach>
	<c:if test="${pagingInfo.next}">
		<a onclick="getPage(${pagingInfo.cri.pageNum + 1});" class="w3-button">»</a>
		<a onclick="getPage(${pagingInfo.lastPage});" class="w3-button">»»</a>
	</c:if>
</div>

 

게시글 추천 기능 ( 프로시저 사용 )

마이 바티스에서 프로시저를 호출해서 게시판 추천 기능을 구현해 보았습니다.

create or replace procedure boardThumbsUp
(
    m_no in number,
    b_no in number
)
is
    ck number;
begin
    select 
        count(*)
    into 
        ck
    from 
        SPRINGBOARDTHUMBS 
    where 
        board_no = b_no and member_no = m_no;
        
    if ck = 0 then
        insert into springboardthumbs values(b_no,m_no);
        update springboard set board_likes = board_likes+1 where board_no = b_no;
    else 
        delete from springboardthumbs where board_no = b_no and member_no = m_no;
        update springboard set board_likes = board_likes-1 where board_no = b_no;
    end if;
    
    commit;
    
end;
/

회원번호와 게시글번호를 받아서

해당 게시글에 해당 회원이 추천을 했던 기록이 있다면 해당 기록을 지우고 게시글 추천수를 줄입니다.

해당 게시글에 해당 회원이 추천을 한 기록이 없다면 새로 추천 정보를 insert 하고 추천수를 1 늘립니다.