본문 바로가기
웹개발/SpringBoot

검색 기능 적용하기

by 철없는민물장어 2023. 7. 26.
728x90
반응형

게시물을 제목으로 검색할 수 있는 기능을 만들어본다.

(페이징 적용)


검색 기능 적용하기

1. Repository

public interface ArticleRepository extends JpaRepository<Article,Long> {
	...
    Page<Article> findByTitleContaining(String keyword,Pageable pageable);

}

JpaRepository를 상속받는 레파지토리 인터페이스에, 

findBy{필드명}Containing({타입} 검색어) 형식으로 메소드를 작성한다.

 

나는 Article엔티티에 String타입의 title이 있고, 이 title을 이용해서 검색할것이기 때문에

findByTitleContaining(String keyword) 로 작성했다. 

그럼, title필드에 keyword가 포함되는 엔티티를 반환받을 수 있다.

SELECT * FROM articles WHERE title LIKE '%Spring%';

만약 findByTitleContaining("Spring")을 호출하면 위와 같은 쿼리가 나간다.

 

또한, 페이징을 위해 파라미터에 Pageable을 추가하고, 반환타입을 Page<Article>로 작성하였다.

 

2. Controller

 

    @GetMapping("/forum/search")
    public String searchArticle(@RequestParam String keyword,@PageableDefault(sort = "id", size=2,direction = Sort.Direction.DESC)
    Pageable pageable, Model model){
        Page<ArticleDto> articlePage = articleService.searchByTitle(pageable, keyword);

        model.addAttribute("articlePage",articlePage);
        model.addAttribute("hasPrev",articlePage.hasPrevious());
        model.addAttribute("hasNext",articlePage.hasNext());
        model.addAttribute("previous",articlePage.previousOrFirstPageable().getPageNumber());
        model.addAttribute("next",articlePage.nextOrLastPageable().getPageNumber());
        model.addAttribute("keyword",keyword);
        return "articles/search";
    }

/forum/search로 접속하면 검색결과를 볼 수 있도록 했다.

검색어를 @RequestParam String keyword로 받았고, 페이징을 위해 파라미터에 Pageable을 추가했다. 또, 뷰로 값을 전달하기 위해 Model을 파라미터에 추가했다.

 

파라미터로 받은 pageable과 keyword를 서비스 메소드로 넘겨 Page<ArticleDto>를 반환받는다.

 

3. Service

 

    public Page<ArticleDto> searchByTitle(Pageable pageable, String keyword) {
        Page<ArticleDto> articleDtos = articleRepository.findByTitleContaining(keyword,pageable).map(ArticleDto::createArticleDto);
        return articleDtos;
    }

pageable과 keyword를 파라미터로 받고, 레파지토리에 작성해둔 메소드 findByTitleContaining을 호출하여 Page<Article> 객체를 반환받는다. Page<ArticleDto>로 변환하기 위해 .map메소드를 이용하였다.

 

4.View

{{>layouts/header}}

<div class="input-group mb-3">
    <input type="text" class="form-control" id="keywordInput" placeholder="제목" >
    <button class="btn btn-outline-secondary" type="button" id="searchButton">검색</button>
</div>

<h2>"{{keyword}}"에 대한 검색 결과</h2>
{{#articlePage.content}}
    <div class="card mt-3">
        <div class="card-body">
            <h5 class="card-title"><a href="/forum/{{id}}">{{title}}</a></h5>
            <h6 class="card-subtitle mb-2 text-muted">{{nickname}}/{{createdAt}}</h6>
        </div>
    </div>
{{/articlePage.content}}
<a href="/forum/new" class="btn btn-outline-primary mt-3">create article</a>
<!-- 현재 페이지 번호 출력 -->
<p>Current Page: {{articlePage.number}}</p>

<!-- 총 페이지 수 출력 -->
<p>Total Pages: {{articlePage.totalPages}}</p>

<!-- 총 엔티티 수 출력 -->
<p>Total Elements: {{articlePage.totalElements}}</p>


<div class="pagination justify-content-center">
    {{#hasPrev}}
        <a href="?keyword={{keyword}}&page={{previous}}" role="button" class="btn btn-lg btn-danger bi bi-caret-left-square-fill"><</a>
    {{/hasPrev}}
    {{^hasPrev}}
        <a href="?keyword={{keyword}}&page={{previous}}" role="button" class="btn btn-lg btn-danger bi bi-caret-left-square-fill disabled"><</a>
    {{/hasPrev}}

    {{#hasNext}}
        <a href="?keyword={{keyword}}&page={{next}}" role="button" class="btn btn-lg btn-primary bi bi-caret-right-square-fill">></a>
    {{/hasNext}}
    {{^hasNext}}
        <a href="?keyword={{keyword}}&page={{next}}" role="button" class="btn btn-primary btn-lg bi bi-caret-right-square-fill disabled">></a>
    {{/hasNext}}
</div>


<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
    $(document).ready(function() {
        // 엔터 키를 누를 때 이벤트 핸들러 등록
        $("#keywordInput").on("keypress", function(event) {
            // 엔터 키의 keycode는 13입니다.
            if (event.keyCode === 13) {
                // 검색 버튼 클릭
                $("#searchButton").click();
            }
        });

        // 검색 버튼 클릭 이벤트 핸들러 등록
        $("#searchButton").on("click", function() {
            // input에서 키워드 가져오기
            var keyword = $("#keywordInput").val();

            // 키워드가 비어있지 않은 경우에만 검색 요청 보내기
            if (keyword.trim() !== "") {
                // 검색 요청 URL 생성
                var searchUrl = "/forum/search?keyword=" + encodeURIComponent(keyword);

                // GET 요청 보내기
                window.location.href = searchUrl;
            }
        });
    });
</script>
{{>layouts/footer}}

Controller로부터 받은 값들을 적절하게 보여준다.

또, 검색창을 두어 검색버튼을 눌렀을 때, /forum/search?keyword=검색어 경로로 get요청을 하도록했다.

728x90
반응형

댓글