본문 바로가기

BackEnd/Spring

[코드로 배우는 스프링 웹 프로젝트] ch15 검색 처리 3(목록, 검색 버튼 이벤트, 수정, 삭제)

728x90
반응형

https://bobo12.tistory.com/312

 

4. 화면에서 검색 조건 처리

   ▷ 페이지 번호가 파라미터로 유지되었던 것처럼 검색 조건과 키워드 역시 항상 화면 이동 시 같이 전송되어야 함

   ▷ 화면에서 검색 버튼을 클릭하면 새로 검색을 한다는 의미이므로 1페이지로 이동

   ▷ 한글의 경우 GET 방식으로 이동하는 경우 문제가 생길 수 있으므로 주의

 

(1) 목록 화면에서 검색 처리

 

◎ llist.jsp 수정(테이블 밑에 search 내용 추가)

<div class='row'>
	<div class="col-lg-12">
		<form id='searchForm' action="/board/list" method='get'>
		<select name='type'>
			<option value="">--</option>
			<option value="T">제목</option>
			<option value="C">내용</option>
			<option value="W">작성자</option>
			<option value="TC">제목 or 내용</option>
			<option value="TW">제목 or 작성자</option>
			<option value="TWC">제목 or 내용 or 작성자</option>
		</select>
		<input type='text' name='keyword' />
		<input type='hidden' name='pageNum'	value='${pageMaker.cri.pageNum}'> 
		<input type='hidden' name='amount' value='${pageMaker.cri.amount}'>
		<button class='btn btn-default'>Search</button>
		</form>
	</div>
</div>


http://localhost:8080/board/list 에서 검색하면 아래와 같은 창이 출력되며 검색 기능도 적용 됩니다.



▷ Chrome 브라우저는 한글로 검색하는 경우 주소창에는 한글이 깨지지 않음
 실제로는 그림에 있는 박스의 내용물 처럼 전송됨
   ▶ 3페이지를 보다가 검색하면 3페이지로 이동하는 문제
   ▶ 검색 후 페이지를 이동하면 검색 조건이 사라지는 문제
   ▶ 검색 후 화면에서는 어떤 검색 조건과 키워드를 이용했는지 알 수 없는 문제들이 있음

 

◎ 검색 버튼의 이벤트 처리

   ▷ 검색 버튼을 클릭하면 검색은 1페이지를 하도록 수정하고, 화면에 검색 조건과 키워드가 보이게 처리하는 작업 우선 진행

 

◎ list.jsp 수정 (검색 버튼 이벤트 처리)

var searchForm = $("#searchForm");
						
$("#searchForm button").on("click", function(e) {
	if(!searchForm.find("option:selected").val()) {
		alert("검색종류를 선택하세요");
		return false;
}
							
	if(!searchForm.find("input[name='keyword']").val()) {
		alert("키워드를 입력하세요");
		return false;
	}
							
	searchForm.find("input[name='pageNum']").val("1");
	e.preventDefault();
							
	searchForm.submit();							
});


윗 부분은 자바스크립트의 내용을 수정한 것
▷ 브라우저에서 검색 버튼을 클릭하면 <form> 태그의 전송은 막고, 페이지 번호는 1이 되도록 처리
 화면에서 키워드가 없다면 검색하지 않도록 제어



◎ select 태그, input 태그 내용 수정
   ▷ 검색 후 주소창에서 검색 조건과 키워드가 같이 GET 방식으로 처리되므로 내용 수정

<form id='searchForm' action="/board/list" method='get'>
	<select name='type'>
	<!-- 
		<option value="">--</option>
		<option value="T">제목</option>
		<option value="C">내용</option>
		<option value="W">작성자</option>
 		<option value="TC">제목 or 내용</option>
		<option value="TW">제목 or 작성자</option>
		<option value="TWC">제목 or 내용 or 작성자</option>
	-->
		<option value="" <c:out value="${pageMaker.cri.type == null ? 'selected' : '' }"/>>
        --</option> 
		<option value="T" <c:out value="${pageMaker.cri.type eq 'T' ? 'selected' : '' }"/>>
        제목</option> 
		<option value="C" <c:out value="${pageMaker.cri.type eq 'C' ? 'selected' : '' }"/>>
        내용</option> 
		<option value="W" <c:out value="${pageMaker.cri.type eq 'W' ? 'selected' : '' }"/>>
        작성자</option> 
		<option value="TC" <c:out value="${pageMaker.cri.type eq 'TC' ? 'selected' : '' }"/>>
        제목 or 내용</option> 
		<option value="TW" <c:out value="${pageMaker.cri.type eq 'TW' ? 'selected' : '' }"/>>
        제목 or 작성자</option> 
		<option value="TWC" <c:out value="${pageMaker.cri.type eq 'TWC' ? 'selected' : '' }"/>>
        제목 or 내용 or 작성자</option>    
	</select>
		<input type='text' name='keyword' value='<c:out value="${pageMaker.cri.keyword}"/>' /> 
		<input type='hidden' name='pageNum' value='<c:out value="${pageMaker.cri.pageNum}"/>' /> 
		<input type='hidden' name='amount' value='<c:out value="${pageMaker.cri.amount}"/>' />
	<button class='btn btn-default'>Search</button>
</form>


 select 태그의 내부는 삼항 연산자를 이용해 해당 조건으로 검색되었다면 selected라는 문자열을 출력하게 해서 화면에서 선택된 항목으로 보이도록 합니다.

◎ 출력 결과
(1) 검색 항목이 선택되지 않은 경우


(2) 키워드를 입력하지 않은 경우


(3) 검색시는 무조건 1페이지로


 검색시 무조건 1페이지로 넘어가고 검색했던 조건들도 그대로 남아있습니다.



◎ form 태그 수정

<form id='actionForm' action="/board/list" method='get'>
	<input type='hidden' name='pageNum' value='${pageMaker.cri.pageNum}'>
	<input type='hidden' name='amount' value='${pageMaker.cri.amount}'>
	<input type='hidden' name='type' value='<c:out value="${pageMaker.cri.type }"/>'>
	<input type='hidden' name='keyword' value='<c:out value="${pageMaker.cri.keyword }"/>'>
</form>


▷ 검색 조건과 키워드에 대한 처리가 되면 검색 후 페이지를 이동해도 동일한 검색 사항들이 계속 유지됨

 

 

(2) 조회 페이지에서 검색 처리

   ▷ 목록 페이지에서 조회 페이지로의 이동은 이미 <form> 태그를 이용해 처리했기 때문에 별도의 처리가 필요 없음

   ▷ 조회 페이지는 아직 Criteria의 type과 keyword에 대한 처리가 없기 때문에 이 부분을 수정해 줄 필요가 있음

 

◎ src/main/webapp/WEB-INF/views/board → get.jsp 수정

<form id='operForm' action="/board/modify" method="get">
	<input type='hidden' id='bno' name='bno' value='<c:out value="${board.bno}"/>'>
	<input type='hidden' name='pageNum' value='<c:out value="${cri.pageNum}"/>'>
	<input type='hidden' name='amount' value='<c:out value="${cri.amount}"/>'>
	<input type='hidden' name='keyword' value='<c:out value="${cri.keyword}"/>'>
	<input type='hidden' name='type' value='<c:out value="${cri.type}"/>'>
</form>

 

 

(3) 수정/삭제 페이지에서 검색 처리

   ▷ 조회 페이지에서 수정/삭제 페이지로의 이동은 GET 방식을 통해서 이동하고, 이동 방식 역시 <form> 태그 이용

   ▷ 기존의 <form> 태그에 추가적인 type과 keyword 조건만을 추가

 

◎ src/main/webapp/WEB-INF/views/board → modify.jsp 수정

<form role="form" action="/board/modify" method="post">
	<input type='hidden' name='pageNum' value='<c:out value="${cri.pageNum }"/>'> 
	<input type='hidden' name='amount' value='<c:out value="${cri.amount }"/>'>
	<input type='hidden' name='type' value='<c:out value="${cri.type }"/>'>
	<input type='hidden' name='keyword' value='<c:out value="${cri.keyword }"/>'>

 

 

 

◎ src/main/java/org.codehows.controller → BoardController 수정

   ▷ 수정/삭제 처리는 BoardController에서 redirect 방식으로 동작하므로 type과 keyword 조건을 같이 리다이렉트시 포함

@PostMapping("/modify")
public String modify(BoardVO board, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) {

	log.info("modify: " + board);

	if (service.modify(board)) {
		rttr.addFlashAttribute("result", "success");
	}
		
	rttr.addAttribute("pageNum", cri.getPageNum()); 
	rttr.addAttribute("amount", cri.getAmount()); 
	rttr.addAttribute("type", cri.getType());
	rttr.addAttribute("keyword", cri.getKeyword());
		
	return "redirect:/board/list";
}

@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, @ModelAttribute("cri") Criteria cri, 
RedirectAttributes rttr) {

	log.info("remove..........." + bno);
	if (service.remove(bno)) {
		rttr.addFlashAttribute("result", "success");
	}

	rttr.addAttribute("pageNum", cri.getPageNum()); 
	rttr.addAttribute("amount", cri.getAmount()); 
	rttr.addAttribute("type", cri.getType());
	rttr.addAttribute("keyword", cri.getKeyword());
		
	return "redirect:/board/list";
}


▷ 리다이렉트는 get 방식으로 이루어지기 때문에 추가적인 파라미터를 처리해야 함 

 

 

◎ src/main/webapp/WEB-INF/views/board → modify.jsp 수정

   ▷ 다시 목록으로 이동하는 경우에 필요한 파라미터만 전송하기 위해 form 태그의 모든 내용을 지우고 다시 추가하는 방식 사용

   ▷ keyword, type 역시 추가하도록 아래와 같이 관련된 JavaScript 코드를 수정해야 함

<script type="text/javascript">
$(document).ready(function() {
	
	var formObj = $("form");
	
	$('button').on("click", function(e){
	    
	    e.preventDefault(); 
		
		var operation = $(this).data("oper");
	    
	    console.log(operation);
		
	    if(operation === 'remove'){
		      formObj.attr("action", "/board/remove");
              
		}else if(operation === 'list'){
		  //move to list
		  formObj.attr("action", "/board/list").attr("method","get");
		  var pageNumTag = $("input[name='pageNum']").clone();
		  var amountTag = $("input[name='amount']").clone();
		  var keywordTag = $("input[name='keyword']").clone();
		  var typeTag = $("input[name='type']").clone();
		  		  
		  formObj.empty();
		  formObj.append(pageNumTag);
		  formObj.append(amountTag);
		  formObj.append(keywordTag);
		  formObj.append(typeTag);
		}
        
		formObj.submit();
	});	
});
</script>


수정/조회 화면에서 어떤 작업을 하던지 다시 목록 페이지로 검색 조건이 유지되는지 확인해야 함

http://localhost:8080/board/list

위의 경로로 접속 시 아래와 같은 화면이 나타나고 수정/조회를 한 이후에도 다시 목록 페이지로 검색 조건이 유지됩니다.

 

 

◎ UriComponentsBuilder를 이용하는 링크 생성

   ▷ 웹페이지에서 매번 파라미터를 유지하는 일이 번거롭다면 UriComponentsBuilder 클래스 이용

   ▷ 여러 개의 파라미터들을 연결해서 URL의 형태로 만들어주는 기능을 가지고 있음

 

◎ Criteria 클래스 내용 추가

   ▷ URL을 만들어주면 리다이렉트 하거나, <form> 태그를 사용하는 상황을 많이 줄여주며 링크 생성 기능 추가

public String getListLink() {
	UriComponentsBuilder builder = UriComponentsBuilder.fromPath("")
			.queryParam("pageNum", this.pageNum)
			.queryParam("amount", this.getAmount())
			.queryParam("type", this.getType())
			.queryParam("keyword", this.getKeyword());
		
	return builder.toUriString();
}


queryParam()이라는 메소드를 이용해 필요한 파라미터들을 손쉽게 추가할 수 있음

Criteria cri = new Criteria();
	cri.setPageNum(3);
    cri.setAmount(20);
    cri.setKeyword("새로");
    cri.setType("TC");


위와 같은 조건들로 Criteria가 생성된다면 getListLink()의 결과는 get 방식에 적합한 URL 인코딩 결과로 만들어짐
(가장 편리한 점은 한글 처리에 신경 쓰지 않아도 된다는 점)

 

◎ src/main/java/org.codehows.controller → BoardController 수정

@PostMapping("/modify")
public String modify(BoardVO board, @ModelAttribute("cri") Criteria cri, RedirectAttributes rttr) {
		
	log.info("modify: " + board);
		
	if(service.modify(board)) {
		rttr.addFlashAttribute("result", "success");			
	}
	/*
	rttr.addAttribute("pageNum", cri.getPageNum());
	rttr.addAttribute("amount", cri.getAmount());
	rttr.addAttribute("type", cri.getType());
	rttr.addAttribute("keyword", cri.getKeyword());
	*/
		
	return "redirect:/board/list" + cri.getListLink();
}
	
@PostMapping("/remove")
public String remove(@RequestParam("bno") Long bno, @ModelAttribute("cri") Criteria cri, 
RedirectAttributes rttr) {
		
	log.info("remove..........." + bno);
	if(service.remove(bno)) {
		rttr.addFlashAttribute("result", "success");
	}
	/*
	rttr.addAttribute("pageNum", cri.getPageNum());
	rttr.addAttribute("amount", cri.getAmount());
	rttr.addAttribute("type", cri.getType());
	rttr.addAttribute("keyword", cri.getKeyword());
	*/
	return "redirect:/board/list" + cri.getListLink();
}


▷ UriComponentsBuilder로 생성된 URL은 화면에서도 유용하게 사용될 수 있는데,
 주로 JavaScript를 사용할 수 없는 상황에서 링크를 처리해야 하는 상황에서 사용 됨

 

목록 페이지나 수정/삭제 페이지들을 script나 BoardController, jsp의 내용을 수정함으로써 모든 기능들을 사용했을 시 검색 조건이 그대로 남아 있는 것을 확인할 수 있었습니다.

 

이렇게 검색까지 가능하도록 홈페이지를 구현해보았습니다!

 

다음은 REST에 대해서 배워볼게요~!!

 

많은 분들의 피드백은 언제나 환영합니다!  많은 댓글 부탁드려요~~

 

 

 

 

728x90
반응형