본문 바로가기
IT

[php] Ajax를 이용하여 실시간 검색 추천어 보여주기

by 당위정 2023. 2. 5.
728x170

 

 

1. 개요

위 구글 검색창과 같이 키워드를 입력할 때 매칭되는 추천 검색어를 보여주는 경우가 많습니다. 이것은 사용자가 정확히 어떤 키워드로 검색을 해야할지 모를 때 도움을 줍니다. 부분적인 검색어를 입력했을 때 다른 사용자들은 어떤 검색어를 주로 사용하는지를 보여주거나, 서비스 공급자가 의도한 방향으로 검색어를 완성할 수 있도록 유도하기에도 좋습니다.

 

오늘은 Ajax를 사용하여 사용자가 검색어를 입력할 때, 입력된 글자에 매칭되는 추천 검색어를 실시간으로 보여주는 방법을 설명드리겠습니다.

 

2. 구현 목표 및 결과물

 

 

위 스크린샷과 같이 input 폼에 텍스트를 입력했을 때 입력된 텍스트와 일치되는 추천 키워드를 보여주는 것입니다. 추천 키워드를 마우스로 클릭하면 input 폼에 자동으로 입력이 되고, 키보드의 상/하 방향키를 이용하여 추천 키워드를 선택할 수도 있습니다.

 

3. 코드 

input 폼이 들어가는 검색 페이지를 index.php 로 작성합니다.

index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<html>
  <head>
      <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
      var selected = -1;
      function search() {
        var keyword = $("#keyword").val();
        if (keyword.length == 0) {
          $("#submit").attr("disabled"true);
        } else {
          $("#submit").removeAttr("disabled");
        }
        $.ajax({
          type: "POST",
          url: "search.php",
          data: { keyword: keyword },
          success: function(result) {
            $("#result").html(result);
            $("#result").find("span").click(function() {
              $("#keyword").val($(this).text());
            });
            $("#result").find("span").mouseover(function() {
              selected = $(this).index();
              $("#result").find("span").removeClass("selected");
              $(this).addClass("selected");
            });
          }
        });
      }
      $(document).keydown(function(event) {
        if ($("#result").find("span").length > 0) {
          if (event.keyCode == 40) { // down arrow
            selected = (selected + 1) % $("#result").find("span").length;
            $("#result").find("span").removeClass("selected");
            setInterval(function() {
                $("#result").find("span").eq(selected).addClass("selected");
            }, 1);
          } else if (event.keyCode == 38) { // up arrow
            selected = (selected - 1 + $("#result").find("span").length) % $("#result").find("span").length;
            $("#result").find("span").removeClass("selected");
            setInterval(function() {
                $("#result").find("span").eq(selected).addClass("selected");
            }, 1);
          } else if (event.keyCode == 13) { // enter
            if (selected != -1) {
              $("#keyword").val($("#result").find("span").eq(selected).text());
            }
          }
        }
      });
    </script>
    <style>
      .selected {
        background-color: lightgray;
      }
    </style>
  </head>
  <body>
    <input type="text" id="keyword" onkeyup="search()">
    <input type="submit" id="submit" value="Submit" disabled>
    <div id="result"></div>
  </body>
</html>
cs

 

  • 입력된 텍스트를 실시간으로 search.php로 전송하여 일치하는 추천 키워드가 있으면 addClass("selected") 로 CSS를 적용합니다. 
  • keydown 이벤트를 이용하여 키보드 방향키로 추천 검색어를 선택할 수 있도록 합니다. 이때 input 폼의 커서가 깜빡일 때 포커스가 이동하면서 selected class가 해제되는 문제가 발생하기 때문에 setInterval 함수를 이용하여 selected class를 유지시킵니다.

 

검색할 대상 DB를 search.php 에 array로 리스트업합니다. 요즘은 주로 jason으로 많이들 합니다만, 키워드만 검색하는 경우에는 array를 사용하는 게 좀더 심플합니다. 아래 예제 파일은 array value가 고정되어 있으나, mysql 등 DB에 쿼리를 하여 실시간으로 불러올 수도 있습니다.

search.php

1
2
3
4
5
6
7
8
9
10
11
12
<?php
  $array = array("바나나""감자""자두""딸기""자몽""바나리스""date""data");
  if (isset($_POST["keyword"])) {
    $keyword = $_POST["keyword"];
    $result = array_filter($arrayfunction($value) use ($keyword) {
      return strpos($value$keyword!== false && strcmp($value$keyword!= 0;
    });
    echo implode("<br>", array_map(function($value) {
      return "<span>$value</span>";
    }, $result));
  }
?>
cs

 

4. 주의사항

영어 키워드는 특별히 신경 쓸 게 없지만, 키워드가 한글일 경우에는 index.php와 search.php 파일을 반드시 UTF-8 형식으로 저장하여 사용하시기 바랍니다. 만약 UTF-8이 아닌 다른 인코딩 형식으로 작성되어 있으면, 한국어를 제대로 처리하지 못할 수 있습니다.

728x90
그리드형

댓글