ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코드로 배우는 스프링부트 웹 프로젝트 Day 11
    Spring/코드로 배우는 스프링부트 웹 프로젝트 2022. 8. 26. 17:57

    /* Annotation들은 스프링부트 프로젝트의 Annotation 정리 페이지에 따로 정리해두었습니다. */

     

    GuestbookServiceImpl에서 목록을 조회할 때 사용하는 getList()는 기존의 코드를 조금 수정해서 작성

     

    GuestbookServiceImpl 클래스 수정

    @Override
    public PageResultDTO<GuestbookDTO, Guestbook> getList(PageRequestDTO requestDTO) {
        Pageable pageable = requestDTO.getPageable(Sort.by("gno").descending());
    
        BooleanBuilder booleanBuilder = getSearch(requestDTO); // 검색 조건 처리
    
        Page<Guestbook> result = repository.findAll(booleanBuilder, pageable); // Querydsl 사용
    
        Function<Guestbook, GuestbookDTO> fn = (entity -> entityToDto(entity));
    
        return new PageResultDTO<>(result, fn);
    }

     

    테스트 코드로 검색이 잘 이루어지는지 확인

     

    GuestbookServiceTests 수정

    @Test
    public void testSearch() {
        
        PageRequestDTO pageRequestDTO = PageRequestDTO.builder()
                .page(1)
                .size(10)
                .type("tc") // 검색 조건 t, c, w, tc, tw, ...
                .keyword("한글") // 검색 키워드
                .build();
        
        PageResultDTO<GuestbookDTO, Guestbook> resultDTO = service.getList(pageRequestDTO);
    
        System.out.println("PREV: " + resultDTO.isPrev());
        System.out.println("NEXT: " + resultDTO.isNext());
        System.out.println("TOTAL: " + resultDTO.getTotalPage());
    
        System.out.println("------------------------------------------------");
        for (GuestbookDTO guestbookDTO : resultDTO.getDtoList()) {
            System.out.println(guestbookDTO);
        }
    
        System.out.println("=================================================");
        resultDTO.getPageList().forEach(System.out::println);
    }

    제목이나 내용에 "한글" 키워드가 있는지 검색하는 테스트

     

    테스트 과정에서 실행된 쿼리 + 결과

    gno > 0 은 쿼리의 where절에서 처리되지 않는 것을 확인할 수 있음

     

     

    [목록 페이지 검색 처리]

    검색 처리를 하기 위해서는 화면에 검색 타입과 키워드를 입력할 수 있는 UI가 필요함

     

    list.html에 검색 타입과 키워드를 입력할 공간과, 검색 버튼을 추가

     

    list.html

    <form action="/guestbook/list" method="get" id="searchForm">
        <div class="input-group">
            <input type="hidden" name="page" value="1">
            <div class="input-group-prepend">
                <select class="custom-select" name="type">
                    <option th:selected="${pageRequestDTO.type == null}">------</option>
                    <option value="t" th:selected="${pageRequestDTO.type == 't'}">제목</option>
                    <option value="c" th:selected="${pageRequestDTO.type == 't'}">내용</option>
                    <option value="w" th:selected="${pageRequestDTO.type == 't'}">작성자</option>
                    <option value="tc" th:selected="${pageRequestDTO.type == 't'}">제목 + 내용</option>
                    <option value="tcw" th:selected="${pageRequestDTO.type == 't'}">제목 + 내용 + 작성자</option>
                </select>
            </div>
            <input class="form-control" name="keyword" th:value="$pageRequestDTO.keyword}">
            <div class="input-group-append" id="button-addon4">
                <button class="btn btn-outline-secondary btn-search" type="button">Search</button>
                <button class="btn btn-outline-secondary btn-clear" type="button">Clear</button>
            </div>
        </div>
    </form>

    <input type="hidden"> 부분에서 page의 값을 1로 지정한 것은 검색을 진행했을 때 무조건 1페이지를 보여주도록 하기 위함

     

    그런데 실행했을 때 type 설정 부분이 이상했다..

    /guestbook/list

    <select class="custom-select" name="type" style="height:38px">

    일단 style로 height를 지정해주었다..

     

    잘 맞춰지긴 했다.

     

    그런데 지금 발견한 더 이상한 점이 있다.

    Gno가 아니라 Title, Title이 아니라 Writer이 항목 이름이어야 하는데..

     

    바꿨다.

     

    그리고 버튼에 따른 작업 처리도 해주었다.

    <script th:inline="javascript">
    
        var msg = [[${msg}]];
    
        console.log(msg);
    
        if(msg){
            $(".modal").modal();
        }
    
        var searchForm = $("#searchForm");
    
        $('.btn-search').click(function(e) {
            searchForm.submit();
        });
    
        $('.btn-clear').click(function(e) {
            searchForm.empty().submit();
        });
    
    </script>

    clear을 누르면, 모든 검색 관련 내용이 사라지고 목록 1페이지로 이동함

     

    search를 누르면 검색한 내용의 목록 중 1페이지로 이동함

    Search

     

    [페이지 번호와 검색 조건 추가]

     

    목록 페이지의 하단의 검색은 현재 page값만 처리하고 있기 때문에 type과 keyword를 추가해준다.

     

    list.html

    <ul class="pagination h-100 justify-content-center align-items-center">
    
        <li class="page-item" th:if="${result.prev}">
            <a class="page-link" th:href="@{/guestbook/list(page= ${result.start -1}, type=${pageRequestDTO.type}, keyword = ${pageRequestDTO.keyword})}" tabindex="-1">Previous</a>
        </li>
    
        <li th:class=" 'page-item ' + ${result.page == page?'active':''} " th:each="page: ${result.pageList}">
            <a class="page-link" th:href="@{/guestbook/list(page = ${page}, type=${pageRequestDTO.type}, keyword = ${pageRequestDTO.keyword})}">
                [[${page}]]
            </a>
        </li>
    
        <li class="page-item" th:if="${result.next}">
            <a class="page-link" th:href="@{/guestbook/list(page = ${result.end + 1}, type=${pageRequestDTO.type}, keyword = ${pageRequestDTO.keyword})}">Next</a>
        </li>
    
    </ul>

     

    페이지 번호들

     

    [조회 페이지로 이동하는 검색 처리]

     

    특정 글의 번호를 클릭해서 이동하는 검색

        => type과 keyword 항목을 추가해서 처리 가능

     

    list.html

    <tr th:each="dto : ${result.dtoList}">
        <th scope="row">
            <a th:href="@{/guestbook/read(gno = ${dto.gno}, page= ${result.page}, type=${pageRequestDTO.type}, keyword = ${pageRequestDTO.keyword})}">
                [[${dto.gno}]]
            </a>

    위처럼 하면 type과 keyword도 파라미터로 추가 전송됨

     

    [조회 페이지 검색 처리]

     

    기존 조회 페이지는 page값만 처리해서 다시 목록으로 돌아가는 링크를 앞서 처리한 것과 동일하게 type과 keyword를 추가해야 함

     

    read.html

    <a th:href="@{/guestbook/modify(gno = ${dto.gno}, page=${requestDTO.page}, type=${requestDTO.type}, keyword=${requestDTO.keyword})}">
        <button type="button" class="btn btn-primary">Modify</button>
    </a>
    
    <a th:href="@{/guestbook/list(page=${requestDTO.page}, type=${requestDTO.type}, keyword=${requestDTO.keyword})}">
        <button type="button" class="btn btn-info">List</button>
    </a>

    이렇게 하면 목록 페이지에서 특정 검색 조건으로 검색한 후 특정 글로 이동 후, 목록 버튼을 누르면 이전에 검색 조건으로 검색한 페이지로 돌아갈 수 있음

     

    [수정 작업 후 이동 처리]

     

    GuestbookController는 작업이 끝난 후에 redirect로 이동하는 경우가 있음

    • 등록 처리: 1페이지로 이동
    • 삭제 처리: 1페이지로 이동
    • 수정 처리: 조회 페이지로 이동

    수정은 조회 페이지로 이동하기 때문에 검색 조건을 유지해야 함

        => page, type, keyword 처리해야 함

     

    modify.html

    <form action="/guestbook/modify" method="post">
    
        <!-- 페이지 번호 -->
        <input type="hidden" name="page" th:value="${requestDTO.page}">
        <input type="hidden" name="type" th:value="${requestDTO.type}">
        <input type="hidden" name="keyword" th:value="${requestDTO.keyword}">

    type, keyword 추가함

    $(".listBtn").click(function () {
    
        var page = $("input[name='page']");
        var type = $("input[name='type']");
        var keyword = $("input[name='keyword']");
    
        actionForm.empty(); //form 태그의 모든 내용을 지움
        
        actionForm.append(page); //목록 페이지 이동에 필요한 내용을 다시 추가
        actionForm.append(type);
        actionForm.append(keyword);
    
        actionForm
            .attr("action", "/guestbook/list")
            .attr("method", "get");
    
        actionForm.submit();
    });

    type과 keyword도 <form> 태그와 같이 전송하도록 수정함

     

    GuestbookController 클래스

    @PostMapping("/modify")
    public String modify(GuestbookDTO dto, @ModelAttribute("requestDTO") PageRequestDTO requestDTO, RedirectAttributes redirectAttributes) {
    
        log.info("post modify..................................................");
        log.info("dto: " + dto);
    
        service.modify(dto);
    
        redirectAttributes.addAttribute("page", requestDTO.getPage());
        redirectAttributes.addAttribute("type", requestDTO.getType());
        redirectAttributes.addAttribute("keyword", requestDTO.getKeyword());
        redirectAttributes.addAttribute("gno" ,dto.getGno());
    
        return "redirect:/guestbook/read";
    }

    redirect 처리 될 때 검색 조건을 유지하도록 type과 keyword를 추가함

     

     

Designed by Tistory.