spring-mvc/board

Spring legacy 프로젝트 게시판 만들기(6) - 검색

crone 2021. 6. 22. 14:32
 

Spring legacy 프로젝트 게시판 만들기(5) - 게시판 페이징 view

Spring legacy 프로젝트 게시판 만들기(5) - 게시판 페이징 Spring legacy 프로젝트 게시판 만들기(4) - 수정하기 Spring legacy 프로젝트 게시판 만들기(3) - 상세조회 이전글 Spring legacy 프로젝트 게시판 만..

cronex.tistory.com


이번엔 list 중에서 검색하는 기능을 추가하도록 하겠습니다.

 

먼저 jsp를 구성하도록 하겠습니다. 페이징 div 아래 검색 div를 추가하였습니다.

 

- board.jsp(검색 form 추가)

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- taglib 추가 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>페이징 게시판</title>
<style type="text/css">
.table>tbody tr:hover {
	background: rgb(200, 200, 200);
	cursor: pointer;
}

.table tr {
	border-bottom: 1px solid #999;
}

.table {
	padding: 30px;
	margin: 0px auto;
	font-size: 20px;
	font-weight: normal;
}

.table thead {
	border-top: 2px solid #666;
}
</style>

</head>
<body>
	<jsp:include page="../common/sidebar.jsp" />
	<div class="content">
		<div style="padding-top: 100px;">
			
			<table class="table"
				style="border-collapse: collapse; width: 1200px; text-align: center;">
				<colgroup>
					<col width="15%">
					<col width="20%">
					<col width="40%">
					<col width="15%">
				</colgroup>
				<thead>
					<tr>
						<th>번호</th>
						<th>제목</th>
						<th>작성자</th>
						<th>작성일</th>
					<tr>
				</thead>
				<tbody class="board-tbody">
					<!-- forEach로 변경된 body부분 -->
					<c:forEach items="${requestScope.list}" var="board">
						<tr>
							<td>${board.board_id}</td>
							<td>${board.board_title}</td>
							<td>${board.board_writer}</td>
							<td>${board.board_date}</td>
						</tr>
					</c:forEach>
				</tbody>
			</table>

			<!-- 글쓰기 버튼 -->
			<div style="text-align: right; padding-right: 10%; margin-top: 20px;">
				<button id="write">글쓰기</button>
			</div>

			<!-- 페이징 -->
			<div style="text-align: center; margin-top: 30px;">
				<c:choose>
					<c:when test="${empty requestScope.searchValue}">             <!-- 1 -->

						<button id="startPage"><<</button>    <!-- 2 -->

						<c:if test="${requestScope.pageInfo.pageNo <= 1}">    <!-- 3 -->
							<button disabled><</button>
						</c:if>

						<c:if test="${requestScope.pageInfo.pageNo > 1}">    <!-- 4 -->
							<button id="prevPage"><</button>
						</c:if>

						<c:forEach var="p" begin="${requestScope.pageInfo.startPage}" 
							end="${requestScope.pageInfo.endPage}" step="1">               <!-- 5 -->

							<c:if test="${requestScope.pageInfo.pageNo eq p}">       <!-- 6 -->
								<button disabled>
									<c:out value="${p}"></c:out>
								</button>
							</c:if>

							<c:if test="${requestScope.pageInfo.pageNo ne p}">
								<!-- 7 -->
								<button class="paging-button">
									<c:out value="${p}"></c:out>
								</button>
							</c:if>

						</c:forEach>

						<c:if test="${requestScope.pageInfo.pageNo >= requestScope.pageInfo.maxPage}"> <!-- 8 -->
							<button disabled>></button>
						</c:if>

						<c:if test="${requestScope.pageInfo.pageNo < requestScope.pageInfo.maxPage}"> <!-- 9 -->
							<button id="nextPage">></button>
						</c:if>

						<button id="maxPage">>></button>
						<!-- 10 -->

					</c:when>

					<c:otherwise>										<!-- 검색시 페이징 -->
					
					</c:otherwise>
				</c:choose>
			</div>

			<!-- 검색 폼 -->
			<form id="searchForm">
				<div class="search-area" align="center">                        
					<select id="searchCondition" name="type">                
						<option value="writer">작성자</option>
						<option value="title">제목</option>
						<option value="text">내용</option>
					</select> <input type="search" id="searchValue" name="keyword">
					<button type="button" id="search">검색하기</button>
				</div>
			</form>
            
            
		</div>
	</div>
	
	<script type="text/javascript">
	const PAGING_PATH = "${pageContext.servletContext.contextPath}/board";
	$(function(){
		<!-- detail 페이지 이동 js -->
		/*list에서 게시물 클릭 시 해당 게시물 상세 페이지로 이동*/
		$(".board-tbody > tr").on("click", function(){
			let number = $(this).children().eq(0).text(); /*board number*/
			location.href = "${pageContext.servletContext.contextPath}/board/" + number;
		})
		
		// << 버튼 처음 페이지로 이동
		$("#startPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=1";
		})
		
		// < 버튼 이전 페이지로 이동
		$("#prevPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${reqeustScope.pageInfo.pageNo - 1}";
		})													
		
		// > 이 후 페이지로 이동
		$("#nextPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo + 1}";
		})
		
		// >> 끝 페이지로 이동
		$("#maxPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.maxPage}";
		})
		
		// 페이징 버튼 클릭(1,2,3,4,5...) 해당 페이지로 이동
		$(".paging-button").on("click", function(){
			let pageNumber = $(this).text();
			location.href = PAGING_PATH +"?currentPage="+pageNumber;
		})
		
		//작성 버튼 클릭 시 페이지 이동
		$("#write").on("click", function(){
			
			location.href = "${pageContext.servletContext.contextPath}/write";
		})
		
	})
</script>
</body>
</html>

 

브라우저에서 확인해 보면 아래와 같습니다.

 

검색 추가

 

 

검색하기 버튼을 누를 때 동작 할 함수를 작성하도록 하겠습니다.

 

-board.jsp

		// 검색 버튼 클릭 시 
		$("#search").on("click", function(){
			
			let $type = $("#searchCondition").children(":selected");
			let $keyword = $("#searchValue").val();
			
			if($keyword == "") {
				alert("검색어를 입력해 주세요")
			}else{
				$("#searchForm").attr("action", PAGING_PATH);
				$("#searchForm").attr("method", "get");
				$("#searchForm").submit();
			}
		})
        

 

기존에 list요청을 받는 controller를 수정하여 새로 요청을 받을 controller를 작성하도록 하겠습니다.

 

-BoardController.java

 

package com.js.board.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.js.board.model.dto.BoardDTO;
import com.js.board.model.dto.PageInfoDTO;
import com.js.board.model.dto.SearchDTO;
import com.js.board.model.service.BoardService;
import com.js.board.paging.Pagenation;

@Controller
public class BoardController {

	private static final Logger log = LoggerFactory.getLogger(BoardController.class);
	private final BoardService boardService;
	
	@Autowired
	public BoardController(BoardService boardService) {
		this.boardService = boardService;
	}
	
	/*
	 *board 리스트 페이지 요청 controller
	 *@param model Model 객체
	 *@param currentPage 페이징 번호
	 *@return viewResolver에 전달할 view path String
	 */
	@RequestMapping(value ="/board", method = RequestMethod.GET)
	public String board(Model model,
			   @RequestParam(value="currentPage", defaultValue = "1", required = false) String currentPage,
			   @ModelAttribute SearchDTO search) {
		
	
		/*기본 페이징 값 1로 설정*/
		int pageNo = 1;
		int page;
		
		try {
			page = Integer.parseInt(currentPage);
		}catch(NumberFormatException e){
			page = 1;
		}
		
		/*넘어온 currentPage 값이 0이거나 0보다 작다면 기본적으로 1로 설정*/
		if(page <= 0) {
			pageNo = 1;
		}else {
			pageNo = page;
		}
		
		/*db에 저장되어 있는 게시판 갯수 조회*/
		int totalCount = boardService.totalCount(search);
		
		/*페이징 계산 후 pageInfo에 값을 담는다.*/
		search = (SearchDTO)Pagenation.getPageInfo(pageNo, totalCount, search);
		
		/*starRow, endRow에 해당하는 list 조회*/
		List<BoardDTO> list = boardService.selectBoardList(search);
		
		/*model에 담기*/
		model.addAttribute("list", list);
		model.addAttribute("pageInfo", search);
		
		log.info("list : {}", list);
		log.info("pageInfo : {}", search);
		
		return "board/board";
	}

	


	

	
}

 

기존에서 변경된게 있다면

@ModelAttribute SearchDTO seach PageInfo class를 확장한 객체 type과 keyword를 필드로 갖고있다.
int totalCount 기존에는 매개변수 없이 전체 리스트 갯수를 조회해왔지만  검색어를 통한 리스트 갯수를 조회하기 위해 keyword와 type으로 조회한다.
Pagenation.getPageInfo(pageNo, totalCount, search) 페이징을 계산하여 반환해주는 메소드로 search를 매개변수로 추가로 전달하도록 변경하였습니다.
boardService.selectBoardList(search) 기존에는 list를 1~ 10, 11 ~ 20 ... ROW를 기준으로 조회해 왔다면 검색어를 추가적으로 조회하여 1 ~ 10, 11 ~20...ROW를 기준으로 조회한다.

 

추가된 SearchDTO를 살펴 보도록 하겠습니다.

 

- SearchDTO.java

package com.js.board.model.dto;

public class SearchDTO extends PageInfoDTO implements java.io.Serializable{
	
	private String type; /*검색 타입*/
	private String keyword; /*검색어*/
	
	public SearchDTO() {}
	
	public SearchDTO(String type, String keyword) {
		this.type = type;
		this.keyword = keyword;
	}

	public SearchDTO(int pageNo, int totalCount, int limit, int buttonAmount, int maxPage, int startPage, int endPage,
			int startRow, int endRow) {
		
		super(pageNo, totalCount, limit, buttonAmount, maxPage, startPage, endPage, startRow, endRow);
	}

	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getKeyword() {
		return keyword;
	}
	public void setKeyword(String keyword) {
		this.keyword = keyword;
	}

	@Override
	public String toString() {
		return "SearchDTO [type=" + type + ", keyword=" + keyword + ", toString()=" + super.toString() + "]";
	}

	
	
	
	
}

 

SearchDTO  PageInfo 를 확장한 class 검색어 및 검색 타입을 담을 수 있도록 필드를 추가 하였습니다.

 

기존에 사용하던 PageInfo를 상속받아 SearchDTO.class를 만들었습니다. 페이징 및 정보를 담기 위해 만들었습니다.

 

다음으로 수정된 페이징 계산 class 및 메소드를 보도록 하겠습니다.

 

- Pagenation.java(SearchDTO 매개변수 추가)

package com.js.board.paging;

import com.js.board.model.dto.PageInfoDTO;
import com.js.board.model.dto.SearchDTO;

public class Pagenation {

	public static PageInfoDTO getPageInfo(int pageNo, int totalCount, PageInfoDTO search) {
		
		
		int maxPage;
		int startPage;
		int endPage;
		int startRow;
		int endRow;
		int limit = 10;
		int buttonAmount = 10;
		
		/*총 페이지 수 계산
		 * ex) 123개의 게시물 한 페이지당 10개씩 보여지는 경우 
		 * 짜투리목록이 1페이지 추가로 필요
		 * 1페이지 추가 하기 위해 + 0.9
		 * 뒤에 더하기는 가중치 만큼 더하는 것 10개씩일 때는 하나의 게시물의 가중치는 10% 이니까 0.9
		 * 5개 일때는 게시물 한 개의 가중치는 20% 이니까 0.8
		 * 20개 일때는 게시물 한 개의 가중치는 5% 이니까 0.95
		 * */
//		maxPage = (int) (((double) totalCount / limit) + 0.9);
		maxPage = (int) Math.ceil((double) totalCount / limit); //올림처리
		
		/*현재 페이지에 보여줄 시작페이지 수
		 * 10개씩 보여지게 할 경우
		 * 1, 11, 21, 31...
		 * 5개 씩일 경우
		 * 1, 6, 11, 16,...
		 * 뒤에 덧셈은 버튼 가중치에 대한 덧셈
		 * 앞자리 구해서 + 1
		 * 배수의 + 1
		 * */
//		startPage = (((int) ((double) pageNo / buttonAmount + 0.9)) - 1) * buttonAmount + 1;
		startPage = (int)(Math.ceil((double) pageNo / buttonAmount) - 1) * buttonAmount + 1;
		
		/*
		 * 목록 아래 쪽에 보여질 마지막 페이지 수
		 * */
		endPage = startPage + buttonAmount - 1;
		
		/*maxPage가 더 작은 경우 마지막 페이지가 maxPage가 된다.*/
		if(endPage > maxPage) {
			endPage = maxPage;
		}
		
		/*마지막 페이지는 0이 될수 없기 때문에 게시물이 아무것도 존재하지 않으면 max 페이지와 endPage를 1로 바꿔준다.*/
		if(maxPage == 0 && endPage == 0) {
			maxPage = startPage;
			endPage = startPage;
		}
		
		
		/*조회를 시작할 행의 번호 수와 마지막 행 번호를 계산한다.*/
		startRow = (pageNo - 1) * limit + 1;
		endRow = startRow + limit - 1;
		
		search.setPageNo(pageNo);
		search.setTotalCount(totalCount);
		search.setLimit(limit);
		search.setButtonAmount(buttonAmount);
		search.setMaxPage(maxPage);
		search.setStartPage(startPage);
		search.setEndPage(endPage);
		search.setStartRow(startRow);
		search.setEndRow(endRow);
		
		return search; 
	}
}

 

달라진 점은 검색어 및 검색타입 정보를 갖고 있는 search 객체를 넘겨 받아 페이징 정보를 setter를 이용하여 설정 후 search를 return 하도록 코드를 수정하였습니다.

 

 

-BoardService.java(interface)

package com.js.board.model.service;

import java.util.List;

import com.js.board.model.dto.BoardDTO;
import com.js.board.model.dto.PageInfoDTO;
import com.js.board.model.dto.SearchDTO;

public interface BoardService {
	
	/*select board list*/
	public List<BoardDTO> selectBoardList(PageInfoDTO search);

	/*select board*/
	public BoardDTO selectById(int number);

	/*update board*/
	public void updateById(BoardDTO board);

	/*count board*/
	public int totalCount(SearchDTO search);

	/*insert board*/
	public int insertBoard(BoardDTO board);


}

 

selectBoardList 메소드에 PageInfoDTO 매개변수가 추가되었습니다.

 

- BoardServiceImpl.java

package com.js.board.model.service;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.js.board.model.dto.BoardDTO;
import com.js.board.model.dto.PageInfoDTO;
import com.js.board.model.dto.SearchDTO;
import com.js.board.model.repository.BoardRepository;

@Service("boardService")
public class BoardServiceImpl implements BoardService{

	private final BoardRepository boardRepository;
	private final SqlSessionTemplate sqlSession;
	
	@Autowired
	public BoardServiceImpl(BoardRepository boardRepository, SqlSessionTemplate sqlSession) {
		this.boardRepository = boardRepository;
		this.sqlSession = sqlSession;
	}
	
	/*board list를 조회할 때 사용하는 service method
	 * @param pageInfo 페이징 객체
	 * @return board List 정보 
	 * */
	@Override
	public List<BoardDTO> selectBoardList(PageInfoDTO search) {
		
		return boardRepository.selectBoardList(sqlSession, search);
	}

	/*
	 * board를 조회할 때 사용하는 service method
	 * @param number 게시판 번호
	 * @return board 정보
	 * */
	@Override
	public BoardDTO selectById(int number) {
		
		return boardRepository.selectById(number, sqlSession);
	}

	/*
	 * board를 수정할 때 사용하는 service method
	 * @param board 게시물 수정정보가 담긴 객체
	 * @return 
	 * */
	@Override
	public void updateById(BoardDTO board) {
		
		boardRepository.updateById(board, sqlSession);
	}

	/*
	 *count board list method
	 *@param search 검색정보가 담겨있는 객체
	 *@return count board list  
	 * */
	@Override
	public int totalCount(SearchDTO search) {
		
		return boardRepository.totalCount(sqlSession, search);
	}

	/*
	 * board insert method
	 * @param board 입력한 게시물 정보
	 * return boardNumber
	 * */
	@Override
	public int insertBoard(BoardDTO board) {
		
		int boardNumber = boardRepository.selectNextVal(sqlSession);
		
		board.setBoard_id(boardNumber);
		boardRepository.insertBoard(sqlSession, board);
		
		
		return boardNumber;
	}


}

 

- BoardRepository.java (interface)

package com.js.board.model.repository;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;

import com.js.board.model.dto.BoardDTO;
import com.js.board.model.dto.PageInfoDTO;
import com.js.board.model.dto.SearchDTO;

public interface BoardRepository {

	/*select Board List*/
	public List<BoardDTO> selectBoardList(SqlSessionTemplate sqlSession, PageInfoDTO search);
	
	/*select Board*/
	public BoardDTO selectById(int number, SqlSessionTemplate sqlSession);

	/*update Board*/
	public int updateById(BoardDTO board, SqlSessionTemplate sqlSession);

	/*count board*/
	public int totalCount(SqlSessionTemplate sqlSession, SearchDTO search);

	/*select board nextVal*/
	public int selectNextVal(SqlSessionTemplate sqlSession);

	/*insert board*/
	public void insertBoard(SqlSessionTemplate sqlSession, BoardDTO board);

	/*search count*/
	public int keywordCount(SqlSessionTemplate sqlSession, SearchDTO search);
	
}

 

selectBoardList() 메소드에 PageInfoDTO 매개변수가 추가되었습니다.

 

- BoardRepositoryImpl.java

package com.js.board.model.repository;

import java.util.List;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.stereotype.Repository;

import com.js.board.model.dto.BoardDTO;
import com.js.board.model.dto.PageInfoDTO;
import com.js.board.model.dto.SearchDTO;

@Repository("boardRepository")
public class BoardRepositoryImpl implements BoardRepository{

	/*
	 * board List 조회 Repository method
	 * @param sqlSession    service에서 전달받은 sqlSessionTemplate 쿼리문 실행할 객체
	 * @param pageInfo 페이징 객체
	 * @return db에서 조회한 board List정보
	 * */
	@Override
	public List<BoardDTO> selectBoardList(SqlSessionTemplate sqlSession, PageInfoDTO search) {
		
		return sqlSession.selectList("board.selectList", search);
	}

	/*
	 * board 조회 Repository method
	 * @param number  board 번호
	 * @param sqlSession   service에서 전달받은 sqlSessionTemplate 쿼리문 실행할 객체
	 * @return db에서 조회한 board 정보
	 * */
	@Override
	public BoardDTO selectById(int number, SqlSessionTemplate sqlSession) {
		
		return sqlSession.selectOne("board.selectById", number);
	}

	/*
	 * board update Repository method
	 * @param board 수정할 보드정보 객체
	 * @param sqlSession 쿼리문 실행할 객체
	 * */
	@Override
	public int updateById(BoardDTO board, SqlSessionTemplate sqlSession) {
		
		
		return sqlSession.update("board.updateById", board);
	}
	
	/*count board list Repository
	 * @param sqlSession 쿼리문 실행할 객체
	 * @return 보드리스트 갯수
	 * */
	@Override
	public int totalCount(SqlSessionTemplate sqlSession, SearchDTO search) {
		
		return sqlSession.selectOne("board.totalCount", search);
	}

	/*
	 * board sequence nextval 조회
	 * param sqlSession 쿼리문 실행할 객체
	 * return 시퀀스 nextval 값
	 * */
	@Override
	public int selectNextVal(SqlSessionTemplate sqlSession) {
		return sqlSession.selectOne("board.boardNextval");
	}

	/*
	 * board 정보 db에 입력(insert)
	 * @param sqlSession 쿼리문 실행할 객체
	 * @param board 입력한 board정보
	 * */
	@Override
	public void insertBoard(SqlSessionTemplate sqlSession, BoardDTO board) {
		sqlSession.insert("board.insertBoard", board);
	}

	/*
	 * 조건 검색 게시물 count 
	 * @param sqlSession 쿼리문 실행할 객체
	 * @param search 검색 정보가 담겨있는 객체
	 * */
	@Override
	public int keywordCount(SqlSessionTemplate sqlSession, SearchDTO search) {
		
		return sqlSession.selectOne("board.keywordCount", search);
	}
	
}

 

mapper도 동적쿼리를 이용하여 수정하였습니다. 변경된 쿼리문을 살펴 보도록 하겠습니다.

 

-board-mapper.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

 <mapper namespace="board">
 
 
 	<select id="selectList" resultType="com.js.board.model.dto.BoardDTO" parameterType="com.js.board.model.dto.SearchDTO">
 		SELECT 
               A.RNUM
             , A.BOARD_ID
             , A.BOARD_CATEGORY
             , A.BOARD_WRITER
             , A.BOARD_TITLE
             , A.BOARD_TEXT
             , A.BOARD_DATE
             , A.BOARD_REPLY
             , A.BOARD_LEVEL
             , A.BOARD_STATUS
        FROM(SELECT ROWNUM AS RNUM 
                  , B.BOARD_ID
                  , B.BOARD_CATEGORY
                  , B.BOARD_WRITER
                  , B.BOARD_TITLE
                  , B.BOARD_TEXT
                  , B.BOARD_DATE
                  , B.BOARD_REPLY
                  , B.BOARD_LEVEL
                  , B.BOARD_STATUS
             FROM(SELECT C.BOARD_ID
                       , C.BOARD_CATEGORY
                       , C.BOARD_WRITER
                       , C.BOARD_TITLE
                       , C.BOARD_TEXT
                       , C.BOARD_DATE
                       , C.BOARD_REPLY
                       , C.BOARD_LEVEL
                       , C.BOARD_STATUS
                  FROM BOARD C
                  WHERE BOARD_LEVEL = 0
                  AND BOARD_STATUS = 'N'
                  <if test="(type != null and keyword != null) and (type != '' and keyword != '')">
	 			      <choose>
	 				      <when test="type == 'writer'">
						      AND INSTR(BOARD_WRITER, #{keyword}) > 0 			
	 					  </when>
	 					  <when test="type == 'title'">
	 						  AND INSTR(BOARD_TITLE, #{keyword}) > 0
	 					  </when>
	 					  <when test="type == 'text'">
	 						  AND INSTR(BOARD_TEXT, #{keyword}) > 0
	 					  </when>
	 					  <otherwise>
	 					  </otherwise>
	 				   </choose>
			      </if>
                  ORDER BY C.BOARD_ID DESC
                 ) B
             )A
       WHERE A.RNUM BETWEEN #{startRow} AND #{endRow}
 	</select>
    
    
 	
 	<select id="totalCount" parameterType="com.js.board.model.dto.SearchDTO" resultType="_int">
 		SELECT 
 		       COUNT(*)
 		FROM BOARD
 		WHERE BOARD_LEVEL = 0
 		AND BOARD_STATUS = 'N'
 		
 		<if test="(type != null and keyword != null) and (type !='' and keyword != '') ">
	 		<choose>
	 			<when test="type == 'writer'">
					AND INSTR(BOARD_WRITER, #{keyword}) > 0 			
	 			</when>
	 			<when test="type == 'title'">
	 				AND INSTR(BOARD_TITLE, #{keyword}) > 0
	 			</when>
	 			<when test="type == 'text'">
	 				AND INSTR(BOARD_TEXT, #{keyword}) > 0
	 			</when>
	 			<otherwise>
	 			</otherwise>
	 		</choose>
 		</if>
 		
 	</select>

 	
 </mapper>

 

id = selectList 기존 페이징을 이용하여 조회하던 쿼리문에서 추가적으로 조건을 이용해 검색어 및 검색 타입으로 조회 할 수 있도록 수정하였습니다. 
조건으로는 keyword(검색어), type(검색종류)로 기존(전체) 페이징이라면 keyword와 type이 없으니까 null 조건을 주었고 검색어를 입력하지 않고 검색했을 경우를 대비해 빈문자열일 경우 조건문 안 쿼리는 실행되지않도록 하였습니다.
id = totalCount 위와 같은 조건을 추가하여 조건에 맞는 게시물 숫자를 조회해오도록 수정하였습니다.

 

위에서 설정한 함수에서 볼 수 있듯이 입력을 하지않으면 요청을 보내지 않게 설정하였기 때문에 보통의 방법으로는 null 넘어오지는 않을 것 같습니다. 

검색어를 입력하여 잘 조회해 오는지 보도록 하겠습니다.

 

제목 / 문자

 

type 으로는 제목을 검색어로는 "문자"를 입력한 후 검색하기 버튼을 클릭해 보겠습니다.

DEBUG: board.totalCount - ==>  Preparing: SELECT COUNT(*) FROM BOARD WHERE BOARD_LEVEL = 0 AND BOARD_STATUS = 'N' AND INSTR(BOARD_TITLE, ?) > 0 
DEBUG: board.totalCount - ==> Parameters: 문자(String)
INFO : jdbc.sqlonly - SELECT COUNT(*) FROM BOARD WHERE BOARD_LEVEL = 0 AND BOARD_STATUS = 'N' AND INSTR(BOARD_TITLE, 
'문자') > 0 

INFO : jdbc.resultsettable - 
|---------|
|count(*) |
|---------|
|2        |
|---------|
DEBUG: org.mybatis.spring.SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@189a129b]
DEBUG: org.mybatis.spring.SqlSessionUtils - Creating a new SqlSession
DEBUG: org.mybatis.spring.SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35a0234a] was not registered for synchronization because synchronization is not active
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
DEBUG: org.mybatis.spring.transaction.SpringManagedTransaction - JDBC Connection [jdbc:oracle:thin:@localhost:1521:XE, UserName=BOARD, Oracle JDBC driver] will not be managed by Spring
DEBUG: board.selectList - ==>  Preparing: SELECT A.RNUM , A.BOARD_ID , A.BOARD_CATEGORY , A.BOARD_WRITER , A.BOARD_TITLE , A.BOARD_TEXT , A.BOARD_DATE , A.BOARD_REPLY , A.BOARD_LEVEL , A.BOARD_STATUS FROM(SELECT ROWNUM AS RNUM , B.BOARD_ID , B.BOARD_CATEGORY , B.BOARD_WRITER , B.BOARD_TITLE , B.BOARD_TEXT , B.BOARD_DATE , B.BOARD_REPLY , B.BOARD_LEVEL , B.BOARD_STATUS FROM(SELECT C.BOARD_ID , C.BOARD_CATEGORY , C.BOARD_WRITER , C.BOARD_TITLE , C.BOARD_TEXT , C.BOARD_DATE , C.BOARD_REPLY , C.BOARD_LEVEL , C.BOARD_STATUS FROM BOARD C WHERE BOARD_LEVEL = 0 AND BOARD_STATUS = 'N' AND INSTR(BOARD_TITLE, ?) > 0 ORDER BY C.BOARD_ID DESC ) B )A WHERE A.RNUM BETWEEN ? AND ? 
DEBUG: board.selectList - ==> Parameters: 문자(String), 1(Integer), 10(Integer)
INFO : jdbc.sqlonly - SELECT A.RNUM , A.BOARD_ID , A.BOARD_CATEGORY , A.BOARD_WRITER , A.BOARD_TITLE , A.BOARD_TEXT 
, A.BOARD_DATE , A.BOARD_REPLY , A.BOARD_LEVEL , A.BOARD_STATUS FROM(SELECT ROWNUM AS RNUM 
, B.BOARD_ID , B.BOARD_CATEGORY , B.BOARD_WRITER , B.BOARD_TITLE , B.BOARD_TEXT , B.BOARD_DATE 
, B.BOARD_REPLY , B.BOARD_LEVEL , B.BOARD_STATUS FROM(SELECT C.BOARD_ID , C.BOARD_CATEGORY 
, C.BOARD_WRITER , C.BOARD_TITLE , C.BOARD_TEXT , C.BOARD_DATE , C.BOARD_REPLY , C.BOARD_LEVEL 
, C.BOARD_STATUS FROM BOARD C WHERE BOARD_LEVEL = 0 AND BOARD_STATUS = 'N' AND INSTR(BOARD_TITLE, 
'문자') > 0 ORDER BY C.BOARD_ID DESC ) B )A WHERE A.RNUM BETWEEN 1 AND 10 

INFO : jdbc.resultsettable - 
|---------|---------|---------------|-------------|------------|-----------|-----------|------------|------------|-------------|
|rnum     |board_id |board_category |board_writer |board_title |board_text |board_date |board_reply |board_level |board_status |
|---------|---------|---------------|-------------|------------|-----------|-----------|------------|------------|-------------|
|[unread] |159      |0              |sj           |문자          |문자         |2021-06-21 |[null]      |0           |N            |
|[unread] |158      |0              |js           |문자          |문자         |2021-06-21 |[null]      |0           |N            |
|---------|---------|---------------|-------------|------------|-----------|-----------|------------|------------|-------------|

DEBUG: board.selectList - <==      Total: 2

 

잘 적용된 것을 확인할 수 있습니다.

 

다음으로는 페이지버튼을 클릭하게 되면 이전에 검색했던 검색어가 날아가 기존 전체 리스트를 조회하게 되어버립니다. 아래와 같이 말이죠

 

 

url을 보면  ?type=writer&keyword=sj 쿼리스트링을 통해 요청을 하였는데요, 여기서 2페이지를 클릭하게 되면 

 

 

?currentPage=2 로 변경되면서 기존에 검색이 유지되지 않습니다.

 

그 이유는 현재 페이징을 구성하고 있는 코드들이 기존에 사용하던 전체 리스트 기준으로 되어있기 때문입니다.

페이징부분을 수정을 통해 검색을 유지해보도록 하겠습니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- taglib 추가 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>페이징 게시판</title>
<style type="text/css">
.table>tbody tr:hover {
	background: rgb(200, 200, 200);
	cursor: pointer;
}

.table tr {
	border-bottom: 1px solid #999;
}

.table {
	padding: 30px;
	margin: 0px auto;
	font-size: 20px;
	font-weight: normal;
}

.table thead {
	border-top: 2px solid #666;
}
</style>

</head>
<body>
	<jsp:include page="../common/sidebar.jsp" />
	<div class="content">
		<div style="padding-top: 100px;">
			<div style="margin-bottom : 13px; padding-left : 161px;">
				<button type="button" id="all-button">전체글</button>
			</div>
			<table class="table"
				style="border-collapse: collapse; width: 1200px; text-align: center;">
				<colgroup>
					<col width="15%">
					<col width="20%">
					<col width="40%">
					<col width="15%">
				</colgroup>
				<thead>
					<tr>
						<th>번호</th>
						<th>제목</th>
						<th>작성자</th>
						<th>작성일</th>
					<tr>
				</thead>
				<tbody class="board-tbody">
					<!-- forEach로 변경된 body부분 -->
					<c:forEach items="${requestScope.list}" var="board">
						<tr>
							<td>${board.board_id}</td>
							<td>${board.board_title}</td>
							<td>${board.board_writer}</td>
							<td>${board.board_date}</td>
						</tr>
					</c:forEach>
				</tbody>
			</table>

			<!-- 글쓰기 버튼 -->
			<div style="text-align: right; padding-right: 10%; margin-top: 20px;">
				<button id="write">글쓰기</button>
			</div>

			<!-- 페이징 -->
			<div style="text-align: center; margin-top: 30px;">
				<c:choose>
					<c:when test="${empty requestScope.pageInfo.keyword and 
					                empty requestScope.pageInfo.type}">             <!-- 1 -->

						<button id="startPage"><<</button>    <!-- 2 -->

						<c:if test="${requestScope.pageInfo.pageNo <= 1}">    <!-- 3 -->
							<button disabled><</button>
						</c:if>

						<c:if test="${requestScope.pageInfo.pageNo > 1}">    <!-- 4 -->
							<button id="prevPage"><</button>
						</c:if>

						<c:forEach var="p" begin="${requestScope.pageInfo.startPage}" 
							end="${requestScope.pageInfo.endPage}" step="1">               <!-- 5 -->

							<c:if test="${requestScope.pageInfo.pageNo eq p}">       <!-- 6 -->
								<button disabled>
									<c:out value="${p}"></c:out>
								</button>
							</c:if>

							<c:if test="${requestScope.pageInfo.pageNo ne p}">
								<!-- 7 -->
								<button class="paging-button">
									<c:out value="${p}"></c:out>
								</button>
							</c:if>

						</c:forEach>

						<c:if test="${requestScope.pageInfo.pageNo >= requestScope.pageInfo.maxPage}"> <!-- 8 -->
							<button disabled>></button>
						</c:if>

						<c:if test="${requestScope.pageInfo.pageNo < requestScope.pageInfo.maxPage}"> <!-- 9 -->
							<button id="nextPage">></button>
						</c:if>

						<button id="maxPage">>></button>
						<!-- 10 -->

					</c:when>

					<c:otherwise>										<!-- 검색시 페이징 -->
						<button id="searchStartPage"><<</button>             <!--  11 -->
						
						<c:if test="${requestScope.pageInfo.pageNo <= 1}">    <!--  12 -->
							<button disabled><</button>
						</c:if>
						
						<c:if test="${requestScope.pageInfo.pageNo > 1}">       <!-- 13 -->
							<button id="searchPrevPage"><</button>
						</c:if>

						<c:forEach var="p" begin="${requestScope.pageInfo.startPage}"
							end="${requestScope.pageInfo.endPage}" step="1">        <!--  14 -->
							
							<c:if test="${requestScope.pageInfo.pageNo eq p}">       <!-- 15 -->
								<button disabled>
									<c:out value="${p}"></c:out>
								</button>
							</c:if>
							
							<c:if test="${requestScope.pageInfo.pageNo ne p}">        <!-- 16 -->
								<button class="search-paging-button">
									<c:out value="${p}"></c:out>
								</button>
							</c:if>
							
						</c:forEach>

						<c:if
							test="${requestScope.pageInfo.pageNo >= requestScope.pageInfo.maxPage}">  <!-- 17 -->
							<button disabled>></button>
						</c:if>
						
						<c:if
							test="${requestScope.pageInfo.pageNo < requestScope.pageInfo.maxPage}">   <!-- 18 -->
							<button id="searchNextPage">></button>
						</c:if>
						
						<button id="searchMaxPage">>></button>                 <!-- 19 -->
					</c:otherwise>
				</c:choose>
			</div>

			<!-- 검색 폼 -->
			<form id="searchForm">
				<div class="search-area" align="center">                         <!-- 20 -->
					<select id="searchCondition" name="type">                
						<option value="writer"<c:if test="${requestScope.pageInfo.type eq 'writer' }">selected</c:if>>작성자</option>
						<option value="title" <c:if test="${requestScope.pageInfo.type eq 'title' }">selected</c:if>>제목</option>
						<option value="text" <c:if test="${requestScope.pageInfo.type eq 'text' }">selected</c:if>>내용</option>
					</select> <input type="search" id="searchValue" name="keyword" value="${requestScope.pageInfo.keyword }">
					<button type="button" id="search">검색하기</button>
				</div>
			</form>
		</div>
	</div>
	<!-- detail 페이지 이동 js -->
	<script type="text/javascript">
	const PAGING_PATH = "${pageContext.servletContext.contextPath}/board";
	$(function(){
		
		/*list에서 게시물 클릭 시 해당 게시물 상세 페이지로 이동*/
		$(".board-tbody > tr").on("click", function(){
			let number = $(this).children().eq(0).text(); /*board number*/
			location.href = "${pageContext.servletContext.contextPath}/board/" + number;
		})
		
		// << 버튼 처음 페이지로 이동
		$("#startPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=1";
		})
		
		// < 버튼 이전 페이지로 이동
		$("#prevPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${reqeustScope.pageInfo.pageNo - 1}";
		})													
		
		// > 이 후 페이지로 이동
		$("#nextPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo + 1}";
		})
		
		// >> 끝 페이지로 이동
		$("#maxPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.maxPage}";
		})
		
		// 페이징 버튼 클릭(1,2,3,4,5...) 해당 페이지로 이동
		$(".paging-button").on("click", function(){
			let pageNumber = $(this).text();
			location.href = PAGING_PATH +"?currentPage="+pageNumber;
		})
		
		//작성 버튼 클릭 시 페이지 이동
		$("#write").on("click", function(){
			
			location.href = "${pageContext.servletContext.contextPath}/write";
		})
		
		// 검색 버튼 클릭 시 
		$("#search").on("click", function(){
			
			let $type = $("#searchCondition").children(":selected");
			let $keyword = $("#searchValue").val();
			
			if($keyword == "") {
				alert("검색어를 입력해 주세요")
			}else{
				$("#searchForm").attr("action", PAGING_PATH);
				$("#searchForm").attr("method", "get");
				$("#searchForm").submit();
			}
		})
</script>
</body>
</html>

 

1 조건을 이용하여 keyword(검색어) 와 type(검색 종류) 가 없다면 기존에 사용하던(전체 리스트 페이징)을 사용하도록 하였습니다.
otherwise 검색어를 통해 검색 리스트를 조회하였을 때 페이징 부분입니다.
11 "<<" 버튼 입니다. 검색어를 통한 리스트 목록에서 가장 최신 목록으로 이동합니다.
12 "<" 버튼 입니다. 현재 페이지(pageNo)가 1이거나 1보다 작다면 이전 페이지는 없기 때문에 "disabled" 처리 하였습니다.
13 "<" 버튼입니다. 현재 페이지(pageNo)가 1보다 크다면 이전 페이지가 존재 하기에 "abled" 처리 하였습니다.
14 forEach문을 사용하여 현재 보여지는 시작 페이지(startPage) 부터 (endPage)를 구성합니다.
ex)
[1 2 3 4 5], [11 12 13 14 15]....
15 현재 페이지(pageNo) 가 forEach문을 돌고 있는 값(p)과 같다면 해당 버튼을 "disabled" 처리 합니다. 
16 현재 페이지(pageNo) 가 forEach문을 돌고 있는 값(p)과 다르다면 해당 버튼을 "abled"처리 합니다.
17 ">"버튼 입니다. 현재 페이지(pageNo) 가  나타낼 수 있는 전체 페이지(maxPage)값 보다 크거나 같다면 다음 페이지는 없기 때문에 "disabled"처리 하였습니다.
18 ">"버튼 입니다. 현재 페이지(pageNo)가  나타낼 수 있는 전체 페이지(maxPage)값 보다 작다면 이 후 페이지가 있기 때문에 "abeld" 처리 하였습니다. 
19 ">>" 버튼 입니다. maxPage로 이동합니다.
20 작성 form 태그 입니다. option 태그안에 속성으로 조건식을 설정하여 현재 type이 같은 option에 selected 속성을 부여하도록 설정하였습니다.
검색어 입력 input 태그에도 value로 해당 검색어 값을 갖도록 설정하였습니다.

 

이어서 해당 버튼 클릭 시 동작할 함수를 작성 하도록 하겠습니다.

 

// 검색 페이징 << 버튼 처음 페이지로 이동
		$("#searchStartPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=1&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		// 검색 페이징 < 버튼 이전 페이지로 이동
		$("#searchPrevPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo - 1}&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//검색 페이징 페이지(1,2,3,4,5) 클릭 시 해당 페이지 이동
		$(".search-paging-button").on("click", function(){
			
			let pageNumber = $(this).text();
			location.href = PAGING_PATH + "?currentPage=" + pageNumber +"&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//검색 페이징 > 버튼 이 후 페이지로 이동
		$("#searchNextPage").on("click", function(){
			
			location.href= PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo + 1}&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//검색 페이징 >> 버튼 끝 페이지로 이동
		$("#searchMaxPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.maxPage}&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})

 

마지막으로 다시 전체 리스트를 요청 할 수 있도록 table 윗 부분에 전체글 버튼을 만들었습니다.

아래 board.jsp의 전체 코드입니다

 

-board.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- taglib 추가 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>페이징 게시판</title>
<style type="text/css">
.table>tbody tr:hover {
	background: rgb(200, 200, 200);
	cursor: pointer;
}

.table tr {
	border-bottom: 1px solid #999;
}

.table {
	padding: 30px;
	margin: 0px auto;
	font-size: 20px;
	font-weight: normal;
}

.table thead {
	border-top: 2px solid #666;
}
</style>

</head>
<body>
	<jsp:include page="../common/sidebar.jsp" />
	<div class="content">
		<div style="padding-top: 100px;">
			<div style="margin-bottom : 13px; padding-left : 161px;">
				<button type="button" id="all-button">전체글</button>
			</div>
			<table class="table"
				style="border-collapse: collapse; width: 1200px; text-align: center;">
				<colgroup>
					<col width="15%">
					<col width="20%">
					<col width="40%">
					<col width="15%">
				</colgroup>
				<thead>
					<tr>
						<th>번호</th>
						<th>제목</th>
						<th>작성자</th>
						<th>작성일</th>
					<tr>
				</thead>
				<tbody class="board-tbody">
					<!-- forEach로 변경된 body부분 -->
					<c:forEach items="${requestScope.list}" var="board">
						<tr>
							<td>${board.board_id}</td>
							<td>${board.board_title}</td>
							<td>${board.board_writer}</td>
							<td>${board.board_date}</td>
						</tr>
					</c:forEach>
				</tbody>
			</table>

			<!-- 글쓰기 버튼 -->
			<div style="text-align: right; padding-right: 10%; margin-top: 20px;">
				<button id="write">글쓰기</button>
			</div>

			<!-- 페이징 -->
			<div style="text-align: center; margin-top: 30px;">
				<c:choose>
					<c:when test="${empty requestScope.pageInfo.keyword and 
					                empty requestScope.pageInfo.type}">             <!-- 1 -->

						<button id="startPage"><<</button>    <!-- 2 -->

						<c:if test="${requestScope.pageInfo.pageNo <= 1}">    <!-- 3 -->
							<button disabled><</button>
						</c:if>

						<c:if test="${requestScope.pageInfo.pageNo > 1}">    <!-- 4 -->
							<button id="prevPage"><</button>
						</c:if>

						<c:forEach var="p" begin="${requestScope.pageInfo.startPage}" 
							end="${requestScope.pageInfo.endPage}" step="1">               <!-- 5 -->

							<c:if test="${requestScope.pageInfo.pageNo eq p}">       <!-- 6 -->
								<button disabled>
									<c:out value="${p}"></c:out>
								</button>
							</c:if>

							<c:if test="${requestScope.pageInfo.pageNo ne p}">
								<!-- 7 -->
								<button class="paging-button">
									<c:out value="${p}"></c:out>
								</button>
							</c:if>

						</c:forEach>

						<c:if test="${requestScope.pageInfo.pageNo >= requestScope.pageInfo.maxPage}"> <!-- 8 -->
							<button disabled>></button>
						</c:if>

						<c:if test="${requestScope.pageInfo.pageNo < requestScope.pageInfo.maxPage}"> <!-- 9 -->
							<button id="nextPage">></button>
						</c:if>

						<button id="maxPage">>></button> <!-- 10 -->

					</c:when>

					<c:otherwise>										<!-- 검색시 페이징 -->
						<button id="searchStartPage"><<</button>             <!--  11 -->
						
						<c:if test="${requestScope.pageInfo.pageNo <= 1}">    <!--  12 -->
							<button disabled><</button>
						</c:if>
						
						<c:if test="${requestScope.pageInfo.pageNo > 1}">       <!-- 13 -->
							<button id="searchPrevPage"><</button>
						</c:if>

						<c:forEach var="p" begin="${requestScope.pageInfo.startPage}"
							end="${requestScope.pageInfo.endPage}" step="1">        <!--  14 -->
							
							<c:if test="${requestScope.pageInfo.pageNo eq p}">       <!-- 15 -->
								<button disabled>
									<c:out value="${p}"></c:out>
								</button>
							</c:if>
							
							<c:if test="${requestScope.pageInfo.pageNo ne p}">        <!-- 16 -->
								<button class="search-paging-button">
									<c:out value="${p}"></c:out>
								</button>
							</c:if>
							
						</c:forEach>

						<c:if
							test="${requestScope.pageInfo.pageNo >= requestScope.pageInfo.maxPage}">  <!-- 17 -->
							<button disabled>></button>
						</c:if>
						
						<c:if
							test="${requestScope.pageInfo.pageNo < requestScope.pageInfo.maxPage}">   <!-- 18 -->
							<button id="searchNextPage">></button>
						</c:if>
						
						<button id="searchMaxPage">>></button>                 <!-- 19 -->
					</c:otherwise>
				</c:choose>
			</div>

			<!-- 검색 폼 -->
			<form id="searchForm">
				<div class="search-area" align="center">                         <!-- 20 -->
					<select id="searchCondition" name="type">                
						<option value="writer"<c:if test="${requestScope.pageInfo.type eq 'writer' }">selected</c:if>>작성자</option>
						<option value="title" <c:if test="${requestScope.pageInfo.type eq 'title' }">selected</c:if>>제목</option>
						<option value="text" <c:if test="${requestScope.pageInfo.type eq 'text' }">selected</c:if>>내용</option>
					</select>
					 <input type="search" id="searchValue" name="keyword" value="${requestScope.pageInfo.keyword }">
					<button type="button" id="search">검색하기</button>
				</div>
			</form>
		</div>
	</div>
	<!-- detail 페이지 이동 js -->
	<script type="text/javascript">
	const PAGING_PATH = "${pageContext.servletContext.contextPath}/board";
	$(function(){
		
		/*list에서 게시물 클릭 시 해당 게시물 상세 페이지로 이동*/
		$(".board-tbody > tr").on("click", function(){
			let number = $(this).children().eq(0).text(); /*board number*/
			location.href = "${pageContext.servletContext.contextPath}/board/" + number;
		})
		
		// << 버튼 처음 페이지로 이동
		$("#startPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=1";
		})
		
		// < 버튼 이전 페이지로 이동
		$("#prevPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${reqeustScope.pageInfo.pageNo - 1}";
		})													
		
		// > 이 후 페이지로 이동
		$("#nextPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo + 1}";
		})
		
		// >> 끝 페이지로 이동
		$("#maxPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.maxPage}";
		})
		
		// 페이징 버튼 클릭(1,2,3,4,5...) 해당 페이지로 이동
		$(".paging-button").on("click", function(){
			let pageNumber = $(this).text();
			location.href = PAGING_PATH +"?currentPage="+pageNumber;
		})
		
		//작성 버튼 클릭 시 페이지 이동
		$("#write").on("click", function(){
			
			location.href = "${pageContext.servletContext.contextPath}/write";
		})
		
		// 검색 버튼 클릭 시 
		$("#search").on("click", function(){
			
			let $type = $("#searchCondition").children(":selected");
			let $keyword = $("#searchValue").val();
			
			if($keyword == "") {
				alert("검색어를 입력해 주세요")
			}else{
				$("#searchForm").attr("action", PAGING_PATH);
				$("#searchForm").attr("method", "get");
				$("#searchForm").submit();
			}
		})
		
		
		// 검색 페이징 << 버튼 처음 페이지로 이동
		$("#searchStartPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=1&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		// 검색 페이징 < 버튼 이전 페이지로 이동
		$("#searchPrevPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo - 1}&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//검색 페이징 페이지(1,2,3,4,5) 클릭 시 해당 페이지 이동
		$(".search-paging-button").on("click", function(){
			
			let pageNumber = $(this).text();
			location.href = PAGING_PATH + "?currentPage=" + pageNumber +"&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//검색 페이징 > 버튼 이 후 페이지로 이동
		$("#searchNextPage").on("click", function(){
			
			location.href= PAGING_PATH + "?currentPage=${requestScope.pageInfo.pageNo + 1}&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//검색 페이징 >> 버튼 끝 페이지로 이동
		$("#searchMaxPage").on("click", function(){
			
			location.href = PAGING_PATH + "?currentPage=${requestScope.pageInfo.maxPage}&type=${requestScope.pageInfo.type}&keyword=${requestScope.pageInfo.keyword}";
		})
		
		//전체페이지
		$("#all-button").on("click", function(){
			
			location.href = PAGING_PATH
		})
	})
</script>
</body>
</html>

 

브라우저에서 확인해보도록 하겠습니다.

 

전체 페이지

 

해당 전체 리스트를 조회하는 페이지에서 작성자(type : writer) , 검색어(keyword : sj)를 입력하여 검색해 보도록 하겠습니다.

 

 

페이지를 넘겼을 때 검색이 유지되는지 확인해 보도록 하겠습니다.

 

 

검색이 유지가 되는 것을 확인할 수 있습니다.