코딩항해기

[실습/Spring] 검색 기능 비동기(ajax)로 변경하기 본문

problem solving/과제&실습 코딩

[실습/Spring] 검색 기능 비동기(ajax)로 변경하기

miniBcake 2024. 10. 14. 15:59

 
 

 

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

기존 수업을 진행하던 spring 프로젝트에 게시글 검색 기능을 추가할 예정이다.계속 개인 실습해오던 코드와 대체로 유사한데 테이블이나 DTO나 조금씩 다른 부분이 있어서 수업 진행 코드로 대체

minibcake.tistory.com

 
기존에 페이지 이동 방식으로 구현했던 검색기능을 비동기 방식으로 변경한다.
 
원래,,, checkNull.js 재사용성을 위해 여러 input태그를 검사했는데 로직을 추가하면서 변경했다.

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

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

    console.log("checkList : ["+check+"]");
    console.log(check);
    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(){
        if(check.value.trim()){
            //빈 값을 가진 check-null이 없었다면 데이터 전송
            console.log("검색 실행");
            search();
        }
        else {
            //빈값이 하나라도 있었다면 안내
            console.log("검색 불가");
            alert("알맞은 값을 입력해주세요.")
        }
    }

    function search (){
        let condition = $('select[name="condition"]').val();
        let keyword = $('input[name="keyword"]').val();

        console.log("condition ["+condition+"]");
        console.log("keyword ["+ keyword+"]");
        
        console.log("검색 데이터 요청");

        //비동기 통신
        $.ajax({
            url: 'searchBoard.do',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({
                keyword: keyword,
                condition: condition,
            }),
            dataType: 'json',
            success: function (data) {
                //확인
                console.log("data [" + data + "] type [" + typeof data + "]");
                console.log(data);

                if(data.length > 0) {
                    //검색 결과가 있다면
                    console.log("data true");
                    $('#boardList').text(''); //초기화
                    Object.values(data).forEach(element => {
                        //데이터 입력
                        //$('#boardList').append("<li>"+element+"</li>"); >> Object object 출력 toString 불가
                        //양식 지정
                        let msg = `ID: ${element.bid}, Content: ${element.content}, Writer: ${element.writer}, WriterName: ${element.name}`;
                        $('#boardList').append("<li>" + msg + "</li>");
                    });
                }
                else {
                    //검색결과가 없을 경우
                    console.log("data false")
                    $('#boardList').html("<li>'"+keyword+"'에 대한 검색 결과가 없습니다.</li>")
                }
            }
        })

    }
}

 

사용한 함수

먼저 검색어가 있는지 확인하는 부분이다. 공백을 검색하거나 빈값을 검색하지 않도록 한다.
 

    function checkNull(){
        if(check.value.trim()){
            //빈 값을 가진 check-null이 없었다면 데이터 전송
            console.log("검색 실행");
            search();
        }
        else {
            //빈값이 하나라도 있었다면 안내
            console.log("검색 불가");
            alert("알맞은 값을 입력해주세요.")
        }
    }

 
검증을 통과하면 search라는 함수를 실행하는데, 이 함수는 비동기 통신을 사용해 받아온 데이터를 화면에 띄워주는 역할을 진행한다.


    function search (){
        let condition = $('select[name="condition"]').val();
        let keyword = $('input[name="keyword"]').val();

        console.log("condition ["+condition+"]");
        console.log("keyword ["+ keyword+"]");
        
        console.log("검색 데이터 요청");

        //비동기 통신
        $.ajax({
            url: 'searchBoard.do',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({
                keyword: keyword,
                condition: condition,
            }),
            dataType: 'json',
            success: function (data) {
                //확인
                console.log("data [" + data + "] type [" + typeof data + "]");
                console.log(data);

                if(data.length > 0) {
                    //검색 결과가 있다면
                    console.log("data true");
                    $('#boardList').text(''); //초기화
                    Object.values(data).forEach(element => {
                        //데이터 입력
                        //$('#boardList').append("<li>"+element+"</li>"); >> Object object 출력 toString 불가
                        //양식 지정
                        let msg = `ID: ${element.bid}, Content: ${element.content}, Writer: ${element.writer}, WriterName: ${element.name}`;
                        $('#boardList').append("<li>" + msg + "</li>");
                    });
                }
                else {
                    //검색결과가 없을 경우
                    console.log("data false")
                    $('#boardList').html("<li>'"+keyword+"'에 대한 검색 결과가 없습니다.</li>")
                }
            }
        })

    }

 
 

Controller

검색결과가 없다면 검색결과가 없다는 것을 안내한다.
이 때 이 비동기 요청을 처리하는 Controller는 searchBoard.do 요청을 캐치해야한다.
 

	@RequestMapping("/searchBoard.do")
	public @ResponseBody List<BoardDTO> searchBoard(@RequestBody BoardDTO boardDTO) {
		log.info("log: /searchBoard.do searchBoard start");
                log.info("log: /searchBoard.do searchBoard dto [{}]", boardDTO);
		return boardService.selectAll(boardDTO);
	}

 
@ResponseBody 어노테이션을 통해 비동기 통신 메서드임을 ViewResolver에게 안내하며 JSON 데이터가 boardDTO에 주입될 수 있도록 @RequestBody 어노테이션을 붙여준다. (logback 사용)
 
주의할 점은 JSON 파일을 다루기 때문에 의존성 주입을 잊지 말아야한다.

        <!--JSON-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>

 
 
이후 확인해보면 페이지 이동 없이 지정한 위치에 데이터가 변경되는 것을 확인할 수 있다.