본문 바로가기

웹 개발(OLD)/Spring Framework(OLD)

스프링 게시판 검색처리(동적 SQL)

ReviewProject.zip


1. 먼저 검색 처리를 위해서는, 게시물 검색을 하고 페이지가 이동되더라도 검색조건과 관련된 파라미터가 페이지 간 유지되어야 한다. 따라서 현재 페이지 번호(page), 페이지당 보여지는 데이터 수(perPageNum), 검색 옵션(searchType), 검색 키워드(keyword)의 네 가지 정보가 필요하다. 이미 Criteria 클래스에서 page, perPageNum을 관리하고 있기 때문에 이를 상속받아 searchType, keyword를 함께 관리하는 SearchCriteria 클래스를 만든다.

(getter & setter, toString() 생략)


2. 그럼 검색처리까지 완료된 게시물 CRUD를 관리할 컨트롤러인 SearchBoardController를 만들고 가장 먼저 리스트 페이지를 띄워본다.
    현재 /sboard/list 경로 뒤에 page, perPageNum, searchType, keyword 의 파라미터가 추가적으로 전달되는 상태이다. 따라서 이 파라미터들을 listGET 메소드의 매개변수로 SearchCriteria를 선언하여 자동으로 수집하도록 한다. 그러면 이 cri에 담겨진 정보들로 검색 조건에 맞는 리스트를 만들어서 "list"라는 이름으로 모델에 담고, 페이지 하단의 페이지네이션에 필요한 정보를 계산해서 "pageMaker" 라는 이름으로 모델에 담아서 list.jsp 로 전달한다.



3. 그러면 목록 페이지인 list.jsp에서는 리스트 페이지에서 목록 페이지로 이동하거나 다른 페이지의 목록리스트로 이동할 때 유지되어야하는 정보가 페이징관련 정보 + 검색조건 정보 이기 때문에 링크시 만들어지는 파라미터처리를 해주어야 한다. 이처럼 원하는 쿼리 스트링을 가진 URI를 생성할 때 UriComponents클래스를 이용하면된다. 현재 페이징 정보를 갖고 있는 Criteria를 PageMaker가 함께 관리하고 있는데, 검색조건을 관리하는 SearchCrietria는 Criteria의 자식클래스이 이므로 PageMaker에서 검색조건까지 쿼리 스트링으로 만들어내는 메소드를 만들어주면된다. 



4. PageMaker클래스에 만들어진 makerSearch()메소드를 이용하여 list.jsp에서 페이징 번호 링크, 조회 페이지 링크시 만들어지는 파라미터들을 만들어주면된다.



5. 그러면 웹페이지의 개발자도구로 조회페이지 링크와 페이지번호 링크가 적절히 생성된 것을 확인할 수 있다. 



6. 이제 조회페이지에서 검색과 관련된 화면처리이다 .즉, 검색옵션을 선택하고 검색키워드를 입력한다음 검색 버튼을 누르면 조건에 맞는 게시물 리스트가 나와야한다.
따라서 select, option 태그로 검색타입선택을 구성하고 input태그로 키워드를 입력받을 수 있도록 화면을 구성한다.

이때 대괄호로 감싸고 체크한 부분은 검색 결과에도 계속 검색 조건이 유지되어야 하기 때문에 검색 조건 정보를 담고 있는 pageMaker를 이용하여 값을 표시 해주기 위함이다.


7. 그러면 이제 검색 버튼을 클릭했을때의 처리이다. 선택된 검색옵션과 입력된 키워드 값을 읽어와서 쿼리 스트링을 구성한 후 이를 처리하는 서버 url로 이동하면된다. 그러면 해당 url에 매핑되는 컨트롤러의 메소드인 listGET메소드에서 쿼리스트링의 파라미터들을 수집하여 검색결과 리스트를 만들어 줄 것이다.


8. 그럼 이제 화면 쪽과 컨트롤러에서의 처리는 끝났고 서비스, 다오, 그리고 SQL 처리를 해주면된다. 
서비스와 다오 쪽은 별다른 것 없이 페이징 + 검색조건 정보를 갖고잇는 SearchCriteria를 매개변수로 받는 메소드를 만들면 되는데, 이전 페이징 처리를 위해 만들었던 메소드와 이름만 다르게 설계해주면된다.

- 서비스

- 다오



9. 문제는 사용자가 검색 조건을 선택하는 것에 따라 쿼리가 바뀌어서 실행되어야 하기 때문에 동적쿼리를 구성해야한다. 이는 MyBatis에서 제공하는 몇몇 표현식들을( if, choose(when, otherwise), foreach 등) 이용하면 해결할 수 있다.

먼저 검색조건에 해당하는 동적 쿼리를 구성하기 위해 if를 이용했다.

근데 이때 검색 조건에 해당하는 동적 쿼리는 페이지네이션 화면 처리에 필요한, 검색처리된 모든 게시물 수를 구하는 쿼리에서도 필요하다. 
즉, 특정 sql문 조각이 여러군데에서 재사용될때 <sql> 여기 </sql> 로 감싸주면된다 .이때 id를 부여하고, 다른 쿼리에서 사용할 때 
<include refid="부여한 id" /> 처럼 이용하면된다.

즉, 먼저 id를 부여한 sql 쿼리 조각이다.


 그리고 이를 이용하여 동적 검색 결과 리스트와 총 게시물 수를 구해내는 쿼리이다. 




10. 그러면 이제 웹 페이지에서 원하는 검색옵션을 선택하고 키워드를 입력하여 검색버튼을 누르면, 그에 맞는 게시물과 페이징이 되는 것을 확인할 수 있다.


11. 이젠 조회페이지에서 '수정, 삭제, 리스트페이지 버튼'을 눌렀을 때 각각 페이징+검색조건 파라미터를 유지시킨채 처리해주면된다.

즉, 리스트 페이지에서 조회페이지로의 링크를 누르면 페이징 + 검색조건을 담고 있는 파라미터들이 함께 서버로 요청이 되기 때문에 /sboard/read에 해당하는 컨트롤러의 메소드에서는 해당 파라미터들을 관리하는 SearchCriteria를 매개변수로 선언하여 파라미터를 수집하면된다. 그리고 수집한 파라미터들을 다시 모델에 담아서 read.jsp에서 접근할 수 있도록 한다.

그러면 read.jsp에서는 hidden타입으로 해당 파라미터들을 아래처럼 form 태그로 갖고 있다가 


수정, 삭제, 리스트 페이지 버튼을 눌렀을 때 알맞은 해당 url로 submit()해주면된다.  


12 .리스트 페이지랑 삭제의 경우 아래 처럼 컨트롤러에서 form태그로 날아온 파라미터값들을 수집하여 적절히 처리해주면된다.
삭제 후, 다시 원래 보고 있던 리스트 페이지로이동하기 위해 addAttribute()로 페이징+검색조건 파라미터들을 담아서 리스트 페이지로 리다이렉트 해주면된다. (리스트 페이지 컨트롤러는 위에 있으니 생략)



13. 업데이트의 경우에는 업데이트 페이지에서 '저장, 취소 버튼' 처리를 해주어야 한다. 취소버튼이야 그냥 원래 보고 있던 리스트 페이지로 이동하면 되니까 url 쿼리 스트링을 아래와 같이 구성하여 서버에서 처리하게 하면된다.


14. 근데 조회페이지에서 검색옵션으로 title을 선택하고 키워드로 '입'을 입력하고 검색버튼을 누른 후, 조회페이지로 이동하였을때,
    url의 keyword 파라미터 값이 %20%20...으로 이상한 값이 붙어나오는 것을 확인했다.

그렇다 보니 '입' 이 아니라 '입     '에 해당하는 제목은 없었기 때문에 의도한 바 와는 다르게 검색결과 리스트가 적절하게 나오지 않았다.


이는 알고보니 아래와 같이 공백이었다. 그러면 list.jsp에서 조회페이지로 링크를 탈때 공백이 생긴다는 의미이므로 코드를 보니까, 아래와 같았다. 그냥 한줄에 보기 너무 길어서 줄바꿈 해준 것이었는데 밑줄 부분에 공백이 생겨서 의도치 않은 공백이 쿼리스트링에 포함됐던 것이다.


따라서 그냥 코드를 한 줄로 이어 붙이고 테스트 해보니 

쿼리 스트링에 공백이 생기지 않고

검색 결과도 적절히 나오는 것을 확인할 수 있었다.

15. 또 한 가지 문제점은 update.jsp에서 저장버튼을 눌렀을때 폼태그의 값들을 따로 action을 정해주지 않은채 submit()해주게 되는데,
원래 form태그에 action을 따로 지정하지 않으면 default로 현재 경로에 해당하는 곳에서 처리해주는 것으로 알고 있었다. 테스트 결과 맡기는 한데, 아래와 같이 검색조건이 이상하게 두 번 겹쳐서 나왔다.

즉, 아래는 검색조건으로 'Title'을 선택후 키워드로 '입니다' 입력하고 검색버튼을 한 번 누른 후의 페이지이다. 여기서 제목을 눌러서 조회페이지로 이동하여 업데이트 버튼을 누른다.


그리고 내용을 수정하고 저장버튼을 누른다.

그러면 다시 리스트페이지로 이동했을때 searchType과 keyword가 두 개 생성됐다.



이 이유는 현재 찾지 못했지만, update.jsp에서 저장 버튼을 눌렀을때 폼태그를 처리하는 곳을 action태그로 직접 명시해준 코드 한 줄을 추가 함으로써 문제는 해결할 수 있었다.

(등록 처리는 생략)

어쨌든, 동적쿼리를 이용한 검색 처리 끝.