포트폴리오 개발일지
2024-06-12 검색조건 유지 두번째 방법 DTO 반환하기
incodingone
2024. 6. 12. 19:10
현재 문제점
1. jsp 의 검색 기능이 모양만 갖춰져 있고 기능 구현이 덜 되어 있음2. 공백 검색 및 sql 인젝션에 취약함
3. 사용자가 검색했던 검색 조건 반환이 이루어지지 않음(해결중)
이전 내용
이전 2024-06-09 에서는 사용자가 검색을 하면 list.jsp 에서 param으로 검색어를, paramValues 로 검색 조건을 찾아서 검색 결과 응답 페이지에서도 사용자가 검색했던 조건들을 유지할수 있게 했다.이번에는 사용자가 검색했던 조건들이 서버측에서 SearchDTO 의 형태로 받기 때문에 응답에도 SearchDTO를 반환하여 list.jsp 에서 SearchDTO를 이용하여 검색조건 유지가 되도록 해봤다.
SearchDTO 보기
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchDTO {
// 검색조건 저장할 Collection
private List<String> types;
// 검색어 저장할 Sring
private String keyword;
}
구현하기
1. 우선 컨트롤러에서 `addAttribute()`를 사용하여 "searchDTO"로 매개변수인 searchDTO를 반환해주었다.
@GetMapping("/list")
public void list(Model model, SearchDTO searchDTO) {
log.info("노트 컨트롤러 list(검색 테스트용) 호출");
log.info(searchDTO);
model.addAttribute("searchDTO", searchDTO);
model.addAttribute("dtoList", noteService.getSearchList(searchDTO));
}
2. list.jsp 에서 searchDTO 의 파라미터를 조건에 따라 출력되도록 했다.
<div class="searchOption">
<c:if test="${not empty searchDTO }">
<c:forEach items="${searchDTO.types}" var="type">
<c:choose>
<c:when test="${type eq 'title'}">
<c:set var="titleStatus" value="true">
</c:when>
<c:when test="${type eq 'content'}">
<c:set var="contentStatus" value="true">
</c:when>
</c:choose>
</c:forEach>
</c:if>
<form action="/note/list" method="get">
제목 검색<input type="checkbox" value="title" name="types" checked >
내용 검색<input type="checkbox" value="content" name="types" checked >
검색어 : <input type="text" name="keyword" <c:if test="${not empty searchDTO.keyword}">value="${searchDTO.keyword}" >
<button type="submit">Search</button>
</form>
</div>
테스트 해보니 잘 되는데 코드 가독성이 별로여서 간결하게 줄일 방법이 없는지 고민해봤다.
코드가 지저분해 지는 가장 큰 이유가 사용자가 검색을 했을때 체크했던 조건의 <input type="checkbox">
를 checked 로 만들어주기 위함이다. 폼태그 위의 내용이 전부 해당 내용이다.
일단 가장 먼저 떠오른건 삼항 연산을 사용하는 방법이다.
<input
type="checkbox" value ="title" name="types"
${searchDTO.types 에 title 이라는 요소가 포함되어 있는지} ? "checked" : ""
>
저기서 types 에 title 이라는 value가 있는지 확인만 하면 되는건데 이건 또 바로 생각이 안난다.. 고민해보고 마저 작성할 예정이다.
고민해도 마땅히 되는건 없어서 그냥 생각나는대로 구현해보기로 했다.
코드 수정하기
우선 어떤 검색 조건인지 확인할수 있는 메소드를 SearchDTO 에 만들었다.
@Data
@ToString
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SearchDTO {
private List<String> types;
private String keyword;
public String checkType(String type) {
if(types != null) {
for (int i = 0; i < types.size(); i++) {
if (types.get(i).equals(type)) {
return types.get(i);
}
}
}
return "Not found";
}
}
사용자가 검색했던 태그의 value 를 매개변수로 넣어 실제로 types 들어 있는 값과 비교 후 일치하면 해당 값을 반환하도록 했다. 일치하는게 없으면 "Not found"를 반환한다.
다음으로 list.jsp 의 내용을 더 간단하게 줄일 수 있었다.
<div class="searchOption">
<form action="/note/list" method="get">
제목 검색
<input type="checkbox" value="title" name="types"
<c:if test="${searchDTO.checkType('title') eq 'title'}">
checked
</c:if>
>
내용 검색
<input type="checkbox" value="content" name="types"
<c:if test="${searchDTO.checkType('content') eq 'content'}">
checked
</c:if>
>
검색어 : <input type="text" name="keyword" >
<button type="submit">Search</button>
</form>
</div>
처음 구현했던 list.jsp에서 checkbox input 태그에 checked를 해주기 위해 사용했던 jstl 을 싹 걷어낼수 있었다.
여기서 작은 문제가 있다. SearchDTO 에 checkType() 반환형을 String으로 해버려서 저렇게 eq 연산을 해서 checked 를 표현해야 한다. 반환형을 수정해서 더 간단하게 해볼수 있을것 같다.
SearchDTO의 checkType()반환형을 수정했다.
public boolean checkType(String type) {
if(types != null) {
for (int i = 0; i < types.size(); i++) {
if (types.get(i).equals(type)) {
return true;
}
}
}
return false;
}
list.jsp 의 checkbox 타입 인풋도 수정해줬다.
<form action="/note/list" method="get">
제목 검색<input type="checkbox" value="title" name="types" ${searchDTO.checkType('title') ? "checked" : ""}>
내용 검색<input type="checkbox" value="content" name="types" ${searchDTO.checkType('content') ? "checked" : ""}>
검색어 : <input type="text" name="keyword" value="${searchDTO.keyword}">
<button type="submit">Search
</form>
수정 후 모든게 다 잘 작동한다!!!!!!!