본문 바로가기

Spring

[Spring] 게시판 검색창 입력 후 페이징 처리시 유지 안되는 경우 해결방법(session 사용)

반응형

문제 상황

게시판 페이징 버튼을 누르면 검색 옵션과 검색어가 풀린다. 그 결과 검색 결과가 1페이지를 넘어가는 양이면 2페이지를 눌렀을 때, 조건에 맞는 데이터를 불러오지 않고 내림차순된 게시판 데이터가 순서대로 출력된다. 

 

session을 사용해서 해결해보자

1) 컨트롤러에서 session을 사용한다. 세션(session)은 웹 애플리케이션에서 클라이언트와 서버 간의 상태를 유지하고 데이터를 저장하는 데 사용되는 중요한 개념이다. 

@Controller
public class BoardController {
	
	@Inject
	public BoardService service;
	
	@Inject
	public SqlSessionTemplate sqlSession;
	
	// 게시글 목록 
	@RequestMapping("/list")
	public String list(@RequestParam Map<String, Object> paramMap, Model model, HttpSession session) {
			
			// 게시글 목록 조회
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
			list = service.list(paramMap);
			
			// 페이징 
			Map<String, Object> pageMap = service.pageMap(paramMap);
			
			// 모델에 추가
			model.addAttribute("list", list);
			model.addAttribute("paramMap", paramMap);
			model.addAttribute("pageMap", pageMap);
			
			//session 사용, 검색어 입력 유지
			String keyword = (String) paramMap.get("keyword");
		    if (keyword != null) {
		        session.setAttribute("searchKeyword", keyword);
		    }
		    
		    //session 사용, 옵션 선택 유지
		    String searchType = (String) paramMap.get("searchType");
		    if (searchType != null) {
		        session.setAttribute("searchType", searchType);
		    }
			return "list2";
	}
	
	// 글쓰기 페이지 이동
	@RequestMapping("/write")
	public String write() {
		return "write"; 
	}
	
	// 글쓰기 
	@RequestMapping("/insert")
	public String insert(@RequestParam Map<String, Object> map
						,HttpServletRequest request) {
		System.out.println("map 변수 내용: " + map);
		int insert = service.insert(map);
		
		return "redirect:list";
	}
	
	// 상세 페이지 이동
	@RequestMapping("/detail")
	public String detail(int seq, Model model, @ModelAttribute BoardDto dto) {
		
		Map<String, Object> detail = sqlSession.selectOne("mapper.detail", seq);
		model.addAttribute("detail", detail);
		
		return "write";
	}	
	
	// 수정하기	
	@RequestMapping("/update")
	public String update(@ModelAttribute BoardDto boardDto, HttpServletRequest request) {
		System.out.println("detail 변수 내용: " + boardDto);
		
		int updt = service.update(boardDto);
		return "redirect:list";
	}
	
	// 삭제하기 
	@RequestMapping("/delete")
	public String delete(Integer[] chk) {
		
		int delete = sqlSession.delete("mapper.delete",chk);
		
		return "redirect:list";
	}
}

 

해당 코드를 해석 해보자. 

//session 사용, 검색어 입력 유지
String keyword = (String) paramMap.get("keyword");
if (keyword != null) {
    session.setAttribute("searchKeyword", keyword);
}

1. paramMap에서 "keyword"라는 이름의 파라미터 값을 가져와서 keyword 변수에 저장한다. 이 파라미터는 사용자가 검색어를 입력한 값을 나타낸다. 

2. 검색어가 null이 아닌 경우, session.setAttribute("searchKeyword", keyword)를 사용하여 세션에 "searchKeyword"라는 이름으로 검색어 값을 저장한다. 

 

//session 사용, 옵션 선택 유지
String searchType = (String) paramMap.get("searchType");
if (searchType != null) {
    session.setAttribute("searchType", searchType);
}

1. 마찬가지로, paramMap에서 "searchType"이라는 이름의 파라미터 값을 가져옵니다. 이 파라미터는 사용자가 선택한 검색 옵션을 나타낸다. 

2. 검색 옵션(searchType)이 null이 아닌 경우, session.setAttribute("searchType", searchType)를 사용하여 세션에 "searchType"라는 이름으로 검색 옵션 값을 저장합니다. 사용자가 선택한 검색 옵션이 세션을 통해 유지된다.

 

아래는  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 prefix="fmt" uri = "http://java.sun.com/jsp/jstl/fmt" %>

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
    <title>게시판 리스트</title>
    <style type="text/css">
    </style>
</head>
<script>
 $(document).ready(function() {
	 // 삭제 버튼 누를 시 
	 $(function(){
			$("#delBtn").click(function(){
				$("#listFrm").attr("action","delete").attr("method","post").submit();
			})
		})
 });
 
 function list(num){
	 	$('#curPage').val(num);
	 	$('#searchBtn').click();
 }
</script>
<body>
<!-- 검색창 -->
<form action="list" method="get">
<div class="search">
	<div>
		<input type="hidden" name="curPage" id="curPage" value="1">
		<input type="hidden" name="pageScale" id="pageScale" value="10">
		<select name="searchType" id="searchType">
		    <option value="sel">선택</option>
		    <option value="name" <% if (session.getAttribute("searchType") != null && session.getAttribute("searchType").equals("name")) { %> selected <% } %>>작성자</option>
		    <option value="subject" <% if (session.getAttribute("searchType") != null && session.getAttribute("searchType").equals("subject")) { %> selected <% } %>>제목</option>
		    <option value="content" <% if (session.getAttribute("searchType") != null && session.getAttribute("searchType").equals("content")) { %> selected <% } %>>제목+내용</option>
		</select>
		<input type = "text" name = "keyword" id = "keyword" 
		<% if (session.getAttribute("searchKeyword") != null) { %> 
           value="<%= session.getAttribute("searchKeyword") %>"
       <% } %>> 
		<input type = "submit" name = "searchBtn" id = "searchBtn" value = "검색"><br>
		<input type = "date" name = "stDate" id = "stDate"> ~ <input type = "date" name = "endDate" id = "endDate">
	</div>
</div>
</form>

<form name = "listFrm" id = "listFrm">
<table border = "1"> 
			<thead> 
				<tr>	
					<th><input type = "checkbox" name = "all"></th>
					<th>글번호</th>
					<th>작성자(ID)</th>
					<th>제목</th>
					<th>작성일</th>
					<th>수정일</th>
					<th>조회수</th>
				</tr>
			</thead>
			<tbody id = "tableBody">
				<c:forEach items="${list}" var = "boardList" varStatus="num">
					<tr id = "trList"> 
						<td><input type = "checkbox" name = "chk" value = "${boardList.seq}"></td>
						<td>${boardList.seq }</td>
						<td>${boardList.name }(${boardList.id })</td>
						<td><a href = "detail?seq=${boardList.seq }">${boardList.subject }</a></td>
						<td><fmt:formatDate value="${boardList.regDate }" pattern="yyyy-MM-dd"/> </td>
						<td><fmt:formatDate value="${boardList.uptDate }" pattern="yyyy-MM-dd"/></td>
						<td>${boardList.viewCnt }</td>
					</tr>
				</c:forEach>
			</tbody>
	</table>
</form>

<!-- 글쓰기, 삭제 버튼 -->
<div class="button-container">
    <input type="button" name="writeBtn" id="writeBtn" value="글쓰기" onclick="location.href='write'">
    <input type="button" name="delBtn" id="delBtn" value="삭제">
</div>

<!-- **처음페이지로 이동 : 현재 페이지 블럭이 0보다 크면 [처음]하이퍼링크를 화면에 출력-->
<c:if test="${pageMap.curBlock > 0}">
   <a href="javascript:list('1')">[처음]</a>
</c:if>

<!-- **이전페이지 블록으로 이동 : 현재 페이지가 1보다 크면 [이전]하이퍼링크를 화면에 출력 -->
<c:if test="${pageMap.curBlock > 1}">
    <a href="javascript:list('${pageMap.prevPage}')">[이전]</a>
</c:if>

<!-- **하나의 블럭에서 반복문 수행 시작페이지부터 끝페이지까지 -->
<c:forEach var="num" begin="${pageMap.blockBegin}" end="${pageMap.blockEnd}">

<!-- **현재 페이지이면 하이퍼링크 제거 -->
<c:choose>
   <c:when test="${num == pageMap.curPage}">
       <span style="color: red">${num}</span>&nbsp;
   </c:when>
   <c:otherwise>
       <a href="javascript:list('${num}')">${num}</a>&nbsp;
   </c:otherwise>
</c:choose>
</c:forEach>

<!-- **다음페이지 블록으로 이동 : 현재 페이지 블럭이 전체 페이지 블럭보다 작거나 같으면 [다음]하이퍼링크를 화면에 출력 -->
<c:if test="${pageMap.curBlock <= pageMap.totBlock}">
    <a href="javascript:list('${pageMap.nextPage}')">[다음]</a>
</c:if>

<!-- **끝페이지로 이동 : 현재 페이지가 전체 페이지보다 작거나 같으면 [끝]하이퍼링크를 화면에 출력 -->
<c:if test="${pageMap.curPage <= pageMap.totPage}">
    <a href="javascript:list('${pageMap.totPage}')">[끝]</a>
</c:if>

</body>
</html>

 

검색 옵션과 검색어에 해당하는 코드만 따로 뽑아서 해석해보자. 

<!-- 검색창 -->
<form action="list" method="get">
<div class="search">
	<div>
		<input type="hidden" name="curPage" id="curPage" value="1">
		<input type="hidden" name="pageScale" id="pageScale" value="10">
		<select name="searchType" id="searchType">
		    <option value="sel">선택</option>
		    <option value="name" <% if (session.getAttribute("searchType") != null && session.getAttribute("searchType").equals("name")) { %> selected <% } %>>작성자</option>
		    <option value="subject" <% if (session.getAttribute("searchType") != null && session.getAttribute("searchType").equals("subject")) { %> selected <% } %>>제목</option>
		    <option value="content" <% if (session.getAttribute("searchType") != null && session.getAttribute("searchType").equals("content")) { %> selected <% } %>>제목+내용</option>
		</select>
		<input type = "text" name = "keyword" id = "keyword" 
		<% if (session.getAttribute("searchKeyword") != null) { %> 
           value="<%= session.getAttribute("searchKeyword") %>"
       <% } %>> 
		<input type = "submit" name = "searchBtn" id = "searchBtn" value = "검색"><br>
		<input type = "date" name = "stDate" id = "stDate"> ~ <input type = "date" name = "endDate" id = "endDate">
	</div>
</div>
</form>

option 태그와 input 태그 안을 보면 if문이 들어있다. searchType 세션이 null이 아니면서 "name"값인 경우 selected 상태가 된다.  selected는 HTML <option> 요소의 속성 중 하나로, 해당 옵션을 초기 선택 상태로 만들 때 사용된다. 즉, 처음 선택한 옵션(제목, 작성자, 제목+내용) 그대로 유지된다. 

 

게시판 검색&#44; 페이징
문제 해결
session을 사용하면 페이지 이동해도 url이 유지된다.

 

반응형