Laravel에서 실시간 검색을 위한 완벽한 가이드

마지막 업데이트 : 5 12월 2025
  • Laravel을 사용하면 AJAX를 사용한 간단한 검색 엔진부터 Laravel Scout 및 Algolia, Meilisearch, Elasticsearch와 같은 외부 검색 엔진을 사용한 고급 전체 텍스트 검색까지 모든 것을 구현할 수 있습니다.
  • 가벼운 검색의 경우 Alpine.js를 사용하거나 기본 페치 요청을 사용하여 프런트엔드에서 필터링하면 서버 과부하를 방지하고 작은 목록에서 사용자 경험을 개선할 수 있습니다.
  • Laravel Scout는 다양한 검색 엔진과의 통합을 중앙화하고, 모델을 검색 가능한 것으로 표시하고, 인덱스를 관리하고, 균일하게 쿼리를 실행하는 것을 쉽게 해줍니다.
  • 엔진(SaaS, 오픈소스 또는 데이터베이스)을 선택할 때는 데이터 양, 검색의 복잡성, 프로젝트의 성능 및 유지 관리 요구 사항을 기준으로 해야 합니다.

Laravel에서 실시간 검색

Laravel을 사용하여 작업을 시작하고 다음이 필요한 경우 즉각적으로 반응하는 실시간 검색 엔진AJAX와 fetch, jQuery, Alpine.js, Scout와 Algolia 또는 Meilisearch, 프런트엔드 필터링 등 수천 가지 가능한 접근 방식 중에서 길을 잃기 쉽습니다. 다행히 Laravel 생태계는 시도 중에 죽지 않고 원활하고 빠른 검색을 설정하는 데 필요한 모든 것을 이미 제공합니다.

이 기사에서는 조립 방법을 알아볼 수 있습니다. Laravel의 다양한 유형의 실시간 검색클래식 AJAX 자동 완성부터 Laravel Scout와 Algolia, Meilisearch, 데이터베이스 자체, 심지어 Elasticsearch와 같은 검색 엔진을 이용한 전체 텍스트 검색까지 가능합니다. 또한, 데이터 양이 적을 때 브라우저에서 직접 데이터를 필터링할 수 있는 Alpine.js를 활용한 가벼운 대안도 찾아볼 수 있습니다.

Laravel의 실시간 검색은 무엇이고 기본 원리는 어떻게 작동합니까?

실시간 검색의 기본 아이디어는 다음과 같습니다. 사용자가 텍스트 필드에 입력할 때쿼리가 트리거되고 페이지 새로고침 없이 결과가 업데이트됩니다. 기술적으로 이는 Laravel 백엔드, 브라우저의 JavaScript, 그리고 JSON 형식의 데이터 교환이라는 세 가지 핵심 구성 요소를 포함합니다.

한편, Laravel은 서버 계층 역할을 합니다. 요청 수신, 검색 매개변수(입력된 텍스트) 해석, 데이터베이스 쿼리, 그리고 일반적으로 JSON 형식의 구조화된 응답 반환을 담당합니다. 이 응답은 성공, 오류 또는 결과를 찾을 수 없음을 나타낼 수 있습니다.

반대쪽 끝에서는, JavaScript는 사용자 이벤트를 수신하는 역할을 합니다. 검색 입력 시, 백엔드로 비동기 요청(AJAX)을 전송하고 브라우저가 전체 새로 고침을 수행하지 않고도 반환된 데이터를 페이지에 표시합니다. 이 작업은 네이티브 Fetch, jQuery AJAX 또는 Alpine.js와 같은 소규모 반응형 라이브러리를 사용하여 수행할 수 있습니다.

이 기본 메커니즘을 사용하면 다음을 빌드할 수 있습니다. 몇 개의 레코드로 간단한 자동 완성Laravel Scout와 같은 라이브러리와 검색에 최적화된 외부 검색 엔진의 지원을 받아 관련성, 페이지 번호 매기기 및 필터 기능을 갖춘 고급 전체 텍스트 검색 엔진까지 제공합니다.

기본 실시간 검색 엔진을 위한 모델, 경로 및 컨트롤러

JavaScript를 살펴보기 전에 Laravel 측이 잘 구성되어 있는지 확인해야 합니다. 검색, 경로 정리를 위한 Eloquent 모델 및 전용 컨트롤러 실시간으로 검색 로직을 관리합니다.

첫 번째 단계는 검색할 테이블을 나타내는 Eloquent 모델을 만드는 것입니다. 국가 테이블과 다음과 같은 모델을 상상해 보세요. 국가 매우 간단하며 타임스탬프가 없고 대량 할당이 허용됩니다.

검색을 위한 최소 Eloquent 모델의 예:

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Pais extends Model
{
use HasFactory;
protected $guarded = [];
public $timestamps = false;
}

여기서는 모델이 표시되어 있습니다. Pais는 표준 Laravel 네임스페이스에 있습니다.Model에서 상속되며, 보호된 배열을 비워 둠으로써 create() 함수로 모든 필드를 할당할 수 있습니다. public $timestamps = false로 타임스탬프를 비활성화하면 테이블에 created_at 및 updated_at 열이 없는 경우 발생하는 문제를 방지할 수 있습니다.

다음 단계는 정의하는 것입니다 검색 엔진 디스플레이와 AJAX 요청을 모두 처리할 경로매우 일반적인 방식은 뷰를 표시하기 위한 GET 경로와 실시간 쿼리를 수신하도록 설계된 POST 경로를 결합하는 것입니다.

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BuscadorController;

Route::get('/', function () {
return view('welcome');
});

Route::get('buscador', [BuscadorController::class, 'index']);
Route::post('buscador', [BuscadorController::class, 'buscar']);

루트 경로는 환영 뷰를 반환하는 반면 URL은 /search는 검색 기능을 위해 예약되어 있습니다.컨트롤러의 index() 메서드는 폼과 검색 입력을 표시하는 반면, search() 메서드는 브라우저에서 전송된 비동기 요청을 처리합니다.

컨트롤러에서 매우 실용적인 패턴을 구현할 수 있습니다. 오류 발생 시 기본 응답 배열을 준비합니다. 실제로 유효한 AJAX 요청이고 쿼리가 문제 없이 실행되는 경우에만 덮어씁니다.

컨트롤러에는 다음이 있을 수 있습니다. 유사한 구조 이:

namespace App\Http\Controllers;

use App\Models\Pais;
use Illuminate\Http\Request;

class BuscadorController extends Controller
{
public function index()
{
return view('welcome');
}

public function buscar(Request $request)
{
$response = [
'success' => false,
'message' => 'Hubo un error',
];

if ($request->ajax()) {
$data = Pais::where('nombre', 'like', $request->texto.'%')
->take(10)
->get();

$response = [
'success' => true,
'message' => 'Consulta correcta',
'data' => $data,
];
}

return response()->json($response);
}
}

이 시점에서 당신은 이미 가지고 있습니다 전체 백엔드 사이클: 들어오는 AJAX 요청, AJAX인지 확인, where like로 쿼리하고 결과 제한 데이터베이스 과부하를 방지하기 위해 take(10)을 사용하여 적절한 수로 응답합니다. 응답은 항상 JSON 형식으로 전송되므로 프런트엔드 작업이 크게 간소화됩니다.

반응형 검색을 위한 Blade 뷰 및 JavaScript 페치

모델, 경로, 컨트롤러가 준비되었으므로 이제 눈에 보이는 부분을 빌드할 차례입니다. 검색 필드와 결과를 표시하는 블록이 있는 양식, 백그라운드에서 요청을 담당하는 JavaScript도 있습니다.

Blade 뷰는 매우 간단할 수 있습니다. CSRF 토큰 Laravel이 POST 요청을 검증하고 사용하기 편리한 검색 입력란에 삽입하는 내용입니다.

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<strong><meta name="csrf-token" content="{{ csrf_token() }}"></strong>
<title>Laravel</title>
</head>
<body>

<form action="" method="post">
<input type="search" name="texto" id="buscar">
</form>

<div id="resultado"></div>

<script>
window.addEventListener('load', function () {
const buscar = document.getElementById('buscar');
const resultado = document.getElementById('resultado');

buscar.addEventListener('keyup', function () {
fetch('/buscador', {
method: 'post',
body: JSON.stringify({ texto: buscar.value }),
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': document.head.querySelector('[name~="csrf-token"][content]').content,
},
})
.then(response => response.json())
.then(data => {
let html = '';
if (data.success) {
html += '<ul>';
for (let i in data.data) {
html += '<li>' + data.data[i].nombre + '</li>';
}
html += '<ul>';
} else {
html += 'No existen resultados';
}
resultado.innerHTML = html;
});
});
});
</script>

</body>
</html>

이 예에서는 스크립트 검색 입력에서 keyup 이벤트를 수신합니다.각 키 입력은 /search 경로에 대한 페치 요청을 트리거합니다. 필드의 현재 텍스트는 JSON 형식으로 전송되며, X-Requested-With와 같은 키 헤더가 포함되어 AJAX임을 나타내며, Laravel의 기본 보안 기능을 우회하기 위한 CSRF 토큰도 함께 전송됩니다.

응답이 도착하면 JSON으로 변환되어 동적으로 생성됩니다. 결과가 포함된 작은 HTML 목록또는 쿼리에서 데이터가 반환되지 않으면 "검색 결과가 없습니다"와 같은 메시지가 표시됩니다. 이 모든 기능은 페이지를 다시 로드하지 않고도 사용자에게 자연스럽게 제공됩니다.

이 패턴은 다음과 같은 작은 UX 세부 사항을 추가하여 더욱 세부화할 수 있습니다. 지연(디바운스) 키 입력 사이에 로더를 표시하거나 네트워크 오류를 처리하여 무언가가 실패했을 때 인터페이스가 정지된 것처럼 보이지 않도록 합니다.

jQuery를 사용하여 Laravel과 AJAX로 라이브 검색

요즘에는 fetch가 많은 인기를 얻었지만, jQuery AJAX는 여전히 매우 인기가 많습니다. 레거시 프로젝트나 이미 구현된 팀에서 사용하는 방식입니다. 아이디어는 정확히 같습니다. 사용자가 입력하는 내용을 캡처하고, 비동기 요청을 보내고, DOM을 새로 고치는 것입니다.

Laravel에서 라이브 검색을 위한 jQuery를 사용하는 일반적인 워크플로는 일반적으로 다음과 같은 기본 단계로 구성됩니다. 특정 경로 정의, 전용 컨트롤러 생성, 검색 입력을 사용하여 Blade 뷰 구축 마지막으로, 입력되는 대로 AJAX를 트리거하는 jQuery 코드를 추가합니다.

이 프로세스는 다음과 같이 작동합니다. 사용자가 입력을 시작하면 jQuery는 서버에 쿼리를 보냅니다. 검색 문자열을 사용합니다. Laravel은 데이터베이스의 정보를 필터링하고, 일치하는 결과를 JSON으로 반환하며, jQuery는 페이지의 HTML 컨테이너를 업데이트하여 일치 항목을 반영합니다. 이 모든 과정이 밀리초 단위로 진행됩니다.

jQuery를 사용하는 장점은 다음과 같습니다. AJAX의 구문을 요약한 것입니다. 프로젝트에 이미 라이브러리가 있다면 읽기가 매우 쉽습니다. 하지만 최신 JavaScript와 네이티브 Fetch를 사용할 수 있다면 필요하지 않을 수도 있는 추가 종속성을 추가하게 됩니다.

Alpine.js를 사용한 프런트엔드에서의 실시간 필터링 및 검색

표시할 데이터가 비교적 작은 경우(예: 50개 미만의 품목), 복잡한 검색 기능을 갖춘 백엔드를 설정하는 것이 항상 좋은 것은 아닙니다. 그런 경우에는 매우 편리한 옵션이 있습니다. Alpine.js를 사용하여 브라우저에서 직접 필터링하세요사용자가 입력하는 동안 서버에 요청을 하지 않습니다.

아이디어는 각 요소(예: 소문자로 된 이름, 설명, 범주)에 대한 검색 문자열을 미리 계산하고, 이를 data-search-text 속성에 저장한 다음, Alpine.js가 나머지 작업을 처리하도록 하는 것입니다. 작성된 텍스트에 따라 요소를 표시하거나 숨기기 검색 필드에서.

Alpine.js 구성 요소는 다음과 유사한 구조를 가질 수 있습니다. 필터항목

{
search: '',
hasResults: true,
selectedValue: '',
init() {
this.$watch('search', () => this.filterItems());
this.$nextTick(() => this.$refs.searchInput?.focus());
},
filterItems() {
const searchLower = this.search.toLowerCase().trim();
const cards = this.$el.querySelectorAll('.item-card');
let visibleCount = 0;

cards.forEach(card => {
const text = card.dataset.searchText || '';
const isVisible = searchLower === '' || text.includes(searchLower);
card.style.display = isVisible ? '' : 'none';
if (isVisible) visibleCount++;
});

this.hasResults = visibleCount > 0;
},
}

보기에서 각 카드 또는 데이터 행은 속성을 갖습니다. data-search-text는 이미 소문자로 준비된 텍스트입니다.따라서 필터는 JavaScript의 includes() 함수로 축소되며, 이는 짧은 목록에 매우 빠릅니다.

<input type="search" x-model="search" x-ref="searchInput" placeholder="Buscar..." />
<div>
<div class="item-card" data-search-text="formulario contacto simple">
<h3>Formulario de contacto</h3>
<p>Formulario de contacto simple</p>
</div>
</div>

또한, 빈 상태 블록은 다음과 같은 경우에만 표시할 수 있습니다. 현재 검색어에 대한 결과가 없습니다.사용자에게 텍스트를 수정하거나 검색 결과를 빈 문자열로 재설정하는 버튼을 제공하여 필드를 지우도록 유도합니다.

이 접근 방식에는 명확한 장점이 있습니다. 검색 중에는 서버 호출이 발생하지 않습니다.상호작용은 사실상 즉각적이며, 로직은 매우 로컬하고 디버깅하기 쉽습니다. 빠른 선택기, 항목 선택 모달 또는 Laravel 페이지에 내장된 작은 카탈로그에 적합합니다.

Laravel Scout: 전문 엔진을 사용한 전체 텍스트 검색

상황이 심각해지고 필요할 때 빠르고 관련성 있고 확장 가능한 전체 텍스트 검색Laravel에서 가장 자연스러운 경로는 Laravel Scout입니다. Scout는 Eloquent 모델을 Algolia, Meilisearch와 같은 검색 엔진, 자체 데이터베이스, 인메모리 컬렉션 또는 외부 컨트롤러를 통한 Elasticsearch와 쉽게 연결할 수 있는 통합 계층입니다.

스카우트를 시작하려면 일반적으로 다음과 같은 작업이 필요합니다. 새로운 Laravel 프로젝트를 생성하거나 기존 프로젝트를 재사용하세요실행하려면 Docker(예: Laravel Sail)를 사용하고 Composer를 사용하여 라이브러리를 설치하세요. 설치가 완료되면 scout.php 설정 파일을 게시하고 사용하려는 드라이버에 맞게 환경 변수를 조정하세요.

일반적인 워크플로는 Composer와 함께 Scout를 설치하고 구성을 게시하는 것입니다. SCOUT_QUEUE=true로 인덱싱 대기열을 활성화합니다. .env 파일에서 리소스 집약적인 작업이 백그라운드에서 처리되도록 하여 애플리케이션 응답 시간을 개선하세요. 또한, DB_HOST가 사용 중인 데이터베이스를 가리키는지 확인해야 합니다. 이는 Docker 컨테이너를 사용하는 경우 특히 중요합니다.

모델이 스카우트 검색에 참여하려면 다음이 필요합니다. 검색 가능 특성을 추가하여 검색 가능으로 명시적으로 표시하려면예를 들어, 제목 필드가 있는 기차 표를 나타내는 Train 모델이 있는 경우 다음과 같이 정의할 수 있습니다.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Train extends Model
{
use Searchable;

protected $fillable = ['title'];

public function searchableAs()
{
return 'trains_index';
}
}

searchableAs 메서드를 사용하면 다음을 수행할 수 있습니다. 검색 엔진에서 인덱스 이름을 사용자 정의합니다.모델에서 파생된 기본 이름을 사용하는 대신, Scout가 이를 대신합니다. 여기서 Scout는 선택한 드라이버에 따라 원격 또는 로컬 인덱스의 생성, 업데이트 및 삭제 작업을 동기화합니다.

Algolia를 활용한 Laravel Scout: 초고속 SaaS 검색

Algolia는 다음에 중점을 둔 SaaS 서비스입니다. 방대한 양의 데이터에서 매우 빠르고 관련성 있는 검색을 제공합니다.인덱스, 관련성 규칙, 동의어 등을 관리하기 위한 웹 패널이 있으며, Scout와 공식 PHP 클라이언트를 통해 Laravel과 매우 잘 통합됩니다.

Algolia를 Scout와 함께 사용하려면 Composer를 사용하여 PHP 클라이언트를 설치하고 .env 파일에 자격 증명(애플리케이션 ID 및 관리자 API 키)을 등록해야 합니다. SCOUT_DRIVER=algolia로 설정 스카우트에게 이 엔진을 사용하도록 지시합니다. Algolia 패널에서 애플리케이션 ID와 관리 키를 모두 얻을 수 있습니다.

환경이 구성되면 다음과 같은 방법을 사용할 수 있습니다. Train::search('text')->페이지 매기기(6) 인덱스된 필드에서 검색을 수행하기 위해 컨트롤러에 직접 전달하고, Blade 뷰에 전달할 준비가 된 페이지 분할된 Eloquent 형식으로 결과를 받습니다.

예를 들면컨트롤러를 가질 수 있습니다 색인 모든 열차를 나열하거나 titlesearch 매개변수가 수신되면 검색을 수행하고, 인덱스에 새 열차를 삽입하는 create 메서드가 있습니다.

public function index(Request $request)
{
if ($request->has('titlesearch')) {
$trains = Train::search($request->titlesearch)->paginate(6);
} else {
$trains = Train::paginate(6);
}

return view('Train-search', compact('trains'));
}

public function create(Request $request)
{
$this->validate($request, ['title' => 'required']);
Train::create($request->all());
return back();
}

해당 뷰에서 결합할 수 있습니다. 신규 열차 등록 양식 그리고 제출 시 검색을 트리거하는 titlesearch 필드가 있는 또 다른 GET 폼이 있습니다. 그런 다음 Laravel에서 생성된 페이지네이션 링크를 활용하여 열차 컬렉션을 반복하고 각 필드를 표로 표시하기만 하면 됩니다.

Meilisearch, 데이터베이스 및 컬렉션을 통한 스카우트

외부 서비스를 피하고 싶으시다면, Meilisearch는 오픈 소스 검색 엔진입니다 로컬 또는 인프라에 배포할 수 있습니다. Scout는 Algolia와 매우 유사한 방식으로 Meilisearch와 통합됩니다. 드라이버를 변경하고 MEILISEARCH_HOST 및 MEILISEARCH_KEY 변수를 .env 파일에 추가하기만 하면 됩니다.

이를 사용하려면 Meilisearch PHP 클라이언트를 설치하고 조정합니다. SCOUT_DRIVER=메일리서치 MEILISEARCH_HOST를 인스턴스 URL(예: http://127.0.0.1:7700)로 지정합니다. 이전 레코드가 이미 있는 경우 php artisan scout:import "App\Models\Train" 명령을 사용하여 인덱싱하여 엔진에서 사용할 수 있도록 할 수 있습니다.

더 작거나 중간 규모의 응용 프로그램에서는 다음을 선택할 수도 있습니다. 스카우트 드라이버 데이터베이스이 기능은 MySQL 또는 PostgreSQL 데이터베이스에서 전체 텍스트 인덱스와 LIKE 명령을 활용합니다. 이 경우 외부 서비스가 필요하지 않습니다. Scout가 데이터베이스 자체를 검색 엔진으로 사용하도록 SCOUT_DRIVER=database 설정하기만 하면 됩니다.

또 다른 흥미로운 옵션은 메모리의 Eloquent 컬렉션에서 작동하는 드라이버 컬렉션이 엔진은 WHERE 절과 컬렉션 필터링을 사용하여 결과를 필터링하며, Laravel에서 지원하는 모든 데이터베이스와 호환됩니다. `SCOUT_DRIVER=collection` 명령을 사용하거나 Scout 설정 파일을 수정하여 더욱 구체적인 설정을 적용할 수 있습니다.

Explorer를 사용하여 Elasticsearch와 통합

검색에 다음이 필요한 경우 엄청난 양의 데이터와 실시간 분석 작업Elasticsearch는 고전적인 프레임워크입니다. Laravel 생태계에서 Scout와 통합하는 현대적인 방법은 Explorer 컨트롤러를 사용하는 것입니다. Explorer 컨트롤러는 모델과 Elasticsearch 클러스터를 연결하는 다리 역할을 합니다.

이를 위해 일반적으로 Docker가 사용되며, 일반적인 서비스(Laravel, MySQL, Redis, Meilisearch 등) 외에도 풍부한 docker-compose 파일이 함께 사용됩니다. Elasticsearch 및 Kibana 컨테이너그런 다음 Composer를 통해 jeroen-g/explorer 패키지를 설치하고 구성 파일을 게시하여 어떤 모델을 인덱싱해야 하는지 나타냅니다.

config/explorer.php 파일에서 indexes 키 아래에 모델을 등록할 수 있습니다. 예를 들어 다음을 추가할 수 있습니다. 앱\모델\트레인::클래스또한, .env 파일에서 SCOUT_DRIVER=elastic으로 Scout 드라이버를 elastic으로 변경하여 모든 것이 Elasticsearch를 가리키도록 합니다.

Train 모델 내에서 Explored 인터페이스를 구현하고 메서드를 재정의해야 합니다. 매핑 가능인덱스로 전송될 필드 맵을 정의합니다. 간단한 예는 다음과 같습니다.

use JeroenG\Explorer\Application\Explored;
use Laravel\Scout\Searchable;

class Train extends Model implements Explored
{
use Searchable;

protected $fillable = ['title'];

public function mappableAs(): array
{
return [
'id' => $this->id,
'title' => $this->title,
];
}
}

지금부터, 동일한 Scout 인터페이스를 사용하여 Elasticsearch에서 검색을 시작할 수 있습니다.Laravel 생태계를 벗어나지 않고도 매우 낮은 응답 시간과 이 엔진의 완전한 쿼리 성능의 이점을 누릴 수 있습니다.

fetch 또는 jQuery를 통한 기본 자동 완성부터 Alpine.js를 통한 프런트엔드 필터링, Laravel Scout 및 다양한 드라이버를 통한 전체 텍스트 검색까지 이러한 모든 접근 방식을 통해 Laravel은 실시간 검색을 구현하기 위한 다양한 옵션을 제공합니다. 귀하의 프로젝트 규모, 필요한 성능, 유지 관리하려는 인프라에 맞춰 제공됩니다.

  비디오 게임 프로그래밍: 시작 방법 - 단계별 가이드