코딩항해기

[과제/Spring] 수업 실습 코드에 게시글 검색 추가하기 본문

problem solving/과제&실습 코딩

[과제/Spring] 수업 실습 코드에 게시글 검색 추가하기

miniBcake 2024. 10. 10. 15:10

 

 

기존 수업을 진행하던 spring 프로젝트에 게시글 검색 기능을 추가할 예정이다.

계속 개인 실습해오던 코드와 대체로 유사한데 테이블이나 DTO나 조금씩 다른 부분이 있어서 수업 진행 코드로 대체했다.

(환경통일)

 

검색 기능 구현하기

  • 검색은 작성자 검색, 게시글 내용 검색 두 가지
  • 비동기 (페이지이동X)가 아닌 페이지 이동 방식으로 구현

추가로 작성자 id가 아닌 이름으로, 검색어가 유지되도록 구현하려고 한다.

 

 

현재 검색종류와 검색어를 입력 받는 부분이 없으므로, View에 해당 form을 추가했다.

<form action="main.do" method="GET">
	<%--검색 창 부분, 만약 검색을 이미 했다면 해당 값을 유지--%>
	<select name="condition">
		<option value="WRITER" ${boardDTO.condition == 'WRITER' ? 'selected' : ''}>작성자</option>
		<option value="CONTENT" ${boardDTO.condition == 'CONTENT' ? 'selected' : ''}>내용</option>
	</select>
		<%--빈값이 넘어가지 않도록 검증할 class : check-null (JS)--%>
	<input class="check-null" type="text" name="keyword" value="${boardDTO.keyword}" placeholder="검색어를 입력하세요." >
	<button type="button">검색</button>
</form>
<%--데이터 출력 부분--%>
<ul>
	<c:forEach var="data" items="${datas}">
		<li>${data}</li>
	</c:forEach>
	<c:if test="${empty datas}">
		<li>'${boardDTO.keyword}'에 대한 검색 결과가 없습니다.</li>
	</c:if>
</ul>

 

만약 condition과 keyword에 대한 데이터가 있다면 (=이미 검색을 한 상태를 의미) 해당 데이터를 표시할 수 있도록 EL식을 작성했다.

 

이 때 빈 값이나 공백이 검색되지 않도록 처리를 추가했다.

이 처리는 controller, view, model 전부 진행할 수 있으며 DAO에서 빈 배열을 반환해 처리하는 방법도 있지만 아예 검색 시도 자체를 막고 싶어 js를 사용했다.

 

//check-null 요소가 빈 값이라면 form 전송을 막는 JS
//재사용성을 위해 요소가 여러 개 일 수 있다고 가정
//버튼 클릭, Enter 검증

window.onload = ()=>{
    const checkList = document.querySelectorAll(".check-null");
    const submitButton = document.querySelector("button");
    const form = document.querySelector("form");

    console.log("checkList : ["+checkList+"]");
    console.log(checkList);
    console.log("submitButton : ["+submitButton+"]");
    console.log(submitButton);
    console.log("form : ["+form+"]");
    console.log(form);

    submitButton.addEventListener("click", checkNull); //검색버튼 클릭 시 검증

    form.addEventListener("keydown", event => {
        if (event.key === "Enter") { //엔터키 입력시
            event.preventDefault();  //검증 없는 폼 제출 방지
            checkNull();  //검증
        }
    });

    function checkNull(){
        flag = false;//빈 값을 가진 check-null이 없다고 가정
        for(let el of checkList){
            if(!el.value.trim()){ //공백일 경우
                flag = true;
                //반복문 종료
                break;
            }
        }
        if(!flag){
            //빈 값을 가진 check-null이 없었다면 데이터 전송
            console.log("검색 실행");
            form.submit();
        }
        else {
            //빈값이 하나라도 있었다면 안내
            console.log("검색 불가");
            alert("알맞은 값을 입력해주세요.")
        }
    }
}

 

이제 입력 받은 데이터를 main.do로 보내게 되기 때문에 해당 요청이 추가될 수 있도록 기존 main 메서드를 수정한다.

Search기능을 따로 분리해 메서드를 작성할 수도 있지만 이런 방식을 사용하면 응집도를 더욱 올릴 수 있다.

	@RequestMapping("/main.do")
	public String main(BoardDTO boardDTO, Model model) {
		//페이지로 전달할 데이터
		//검색결과
		model.addAttribute("datas", boardService.selectAll(boardDTO));
		//포워드방식 응답
		return "main";
	}

 

DTO에 자동 주입되므로 바로 DTO를 보내면 알맞은 쿼리를 완성해 model로부터 데이터를 받아온다.

받은 데이터와 검색 키워드, 검색 타입을 요청에 담아 main으로 포워드 이동한다.

 

boardService에서 데이터를 받아오고 있지만 실질적인 기능은 DAO에 있으므로 DAO에 해당 condition분기를 추가하면 된다. 이 때 기존 condition없이 실행되던 기능이 작동하지 않는 일이 없도록 빈 값이 넘어왔을 때 실행할 기본 값을 설정했다.

 

	private final String SELECTALL = "SELECT BID,CONTENT, b.WRITER, m.NAME FROM BOARD b join member m on b.WRITER = m.MID";
	private final String SELECTALL_SEARCH_CONTENT = "SELECT BID,CONTENT, b.WRITER, m.NAME FROM BOARD b join member m on b.WRITER = m.MID where content like concat('%',?,'%')";
	private final String SELECTALL_SEARCH_WRITER = "SELECT BID,CONTENT, b.WRITER, m.NAME FROM BOARD b join member m on b.WRITER = m.MID where m.NAME = ?";
	private final String INSERT = "INSERT INTO BOARD (CONTENT,WRITER) VALUES(?,?)";
	
	public List<BoardDTO> selectAll(BoardDTO boardDTO) {
		List<BoardDTO> datas = new ArrayList<BoardDTO>();
		
		Connection conn=JDBCUtil.connect();
		PreparedStatement pstmt = null;
		try {
			/////////////////////////////////////////////////////////////
			if(boardDTO.getCondition() == null){ //메인페이지 기본 값
				pstmt = conn.prepareStatement(SELECTALL);
			}
			else if(boardDTO.getCondition().equals("WRITER")){
				pstmt = conn.prepareStatement(SELECTALL_SEARCH_WRITER);
				pstmt.setString(1,boardDTO.getKeyword().trim()); //검색어(데이터정제)
			}
			else if(boardDTO.getCondition().equals("CONTENT")){
				pstmt = conn.prepareStatement(SELECTALL_SEARCH_CONTENT);
				pstmt.setString(1,boardDTO.getKeyword().trim()); //검색어(데이터정제)
			}
			ResultSet rs=pstmt.executeQuery();
			while(rs.next()) {
				BoardDTO data=new BoardDTO();
				data.setBid(rs.getInt("BID"));
					data.setName(rs.getString("NAME"));
				data.setContent(rs.getString("CONTENT"));
				data.setWriter(rs.getString("WRITER"));
				datas.add(data);
			}
			/////////////////////////////////////////////////////////////
		} catch (SQLException e) {
			e.printStackTrace();
		}	
		
		return datas;
	}

 

 

이제 서버를 돌려 확인하면 잘 작동된다.

 

 

 

 

 

(과제 확인 후)+++

디벨롭 해야할 부분이 매우 많았다...

앞으로 진행할 때는 레퍼런스를 충분히 살피고나서 기능을 구현해야겠다.