포트폴리오 개발일지

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&lt;String&gt; types;  

private String keyword;  

public String checkType(String type) {  
    if(types != null) {  
        for (int i = 0; i &lt; 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>


수정 후 모든게 다 잘 작동한다!!!!!!!

현재 문제점

1. 공백 검색 및 sql 인젝션에 취약함