Laravel Scout
번역일: 2026년 6월 25일
Laravel Scout
소개
Laravel Scout는 Eloquent 모델에 전체 텍스트 검색(full-text search) 기능을 손쉽게 추가할 수 있도록 드라이버 기반의 솔루션을 제공합니다. Scout는 모델 옵저버를 활용해 검색 인덱스를 Eloquent 레코드와 자동으로 동기화합니다.
Scout에는 MySQL / PostgreSQL의 전체 텍스트 인덱스와 LIKE 절을 활용하는 내장 database 엔진이 포함되어 있습니다. 외부 서비스 없이 기존 데이터베이스를 그대로 사용할 수 있어, 대부분의 애플리케이션에서는 이것만으로 충분합니다. Laravel에서 사용 가능한 모든 검색 옵션에 대한 개요는 검색 문서를 참고하세요.
오타 허용(typo tolerance), 패싯 필터링(faceted filtering), 대규모 지리 검색(geo-search) 같은 고급 기능이 필요하다면, Algolia, Meilisearch, Typesense 드라이버도 제공합니다. 로컬 개발용 "collection" 드라이버도 있으며, 필요에 따라 커스텀 엔진을 직접 작성할 수도 있습니다.
설치
먼저 Composer로 Scout 패키지를 설치합니다.
composer require laravel/scout설치 후 vendor:publish Artisan 명령으로 Scout 설정 파일을 발행합니다. 이 명령을 실행하면 scout.php 설정 파일이 애플리케이션의 config 디렉터리에 생성됩니다.
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"마지막으로, 검색 기능을 추가하고 싶은 모델에 Laravel\Scout\Searchable 트레이트를 추가합니다. 이 트레이트는 모델 옵저버를 등록하여 모델 변경 사항을 검색 드라이버와 자동으로 동기화합니다.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
}큐 설정
database나 collection 엔진이 아닌 외부 검색 서비스를 사용할 경우, Scout를 본격적으로 사용하기 전에 큐 드라이버를 설정하는 것을 강력히 권장합니다. 큐 워커를 실행하면 검색 인덱스 동기화 작업이 백그라운드에서 처리되어, 웹 요청의 응답 속도가 눈에 띄게 향상됩니다.
큐 드라이버 설정이 완료되면, config/scout.php의 queue 옵션을 true로 변경합니다.
'queue' => true,NOTE
queue 옵션을 false로 설정하더라도, Algolia나 Meilisearch 같은 일부 드라이버는 항상 비동기로 인덱싱합니다. 즉, Laravel 애플리케이션에서 인덱스 작업이 완료되었더라도, 검색 엔진에 새 레코드나 변경 사항이 즉시 반영되지 않을 수 있습니다.
Scout Job이 사용할 연결(connection)과 큐(queue)를 구체적으로 지정하려면, queue 옵션을 배열로 설정합니다.
'queue' => [
'connection' => 'redis',
'queue' => 'scout'
],이렇게 설정한 경우, 해당 연결과 큐를 처리하는 큐 워커도 함께 실행해야 합니다.
php artisan queue:work redis --queue=scout드라이버 사전 요구사항
Algolia
Algolia 드라이버를 사용하려면 먼저 config/scout.php에 Algolia id와 secret 자격 증명을 입력하고, Algolia PHP SDK를 설치합니다.
composer require algolia/algoliasearch-client-phpMeilisearch
Meilisearch는 빠르고 오픈 소스인 검색 엔진입니다. 로컬 환경에 설치하는 방법이 익숙하지 않다면, Laravel의 공식 Docker 개발 환경인 Laravel Sail을 활용할 수 있습니다.
Meilisearch 드라이버를 사용하려면 Meilisearch PHP SDK를 설치합니다.
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle그런 다음, .env 파일에 SCOUT_DRIVER 환경 변수와 Meilisearch 호스트 및 키 정보를 설정합니다.
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=masterKeyMeilisearch에 대한 자세한 내용은 Meilisearch 공식 문서를 참고하세요.
또한 사용 중인 Meilisearch 바이너리 버전과 호환되는 meilisearch/meilisearch-php 버전을 설치해야 합니다. Meilisearch 바이너리 호환성 문서에서 버전 호환 정보를 확인하세요.
WARNING
Meilisearch를 사용하는 애플리케이션에서 Scout를 업그레이드할 때는, Meilisearch 서비스 자체의 추가 변경 사항을 반드시 확인하세요.
Typesense
Typesense는 매우 빠른 오픈 소스 검색 엔진으로, 키워드 검색, 시맨틱 검색, 지리 검색, 벡터 검색을 지원합니다.
자체 호스팅하거나 Typesense Cloud를 이용할 수 있습니다.
Scout와 함께 Typesense를 사용하려면 Typesense PHP SDK를 설치합니다.
composer require typesense/typesense-php그런 다음, .env 파일에 SCOUT_DRIVER 환경 변수와 Typesense 호스트 및 API 키를 설정합니다.
SCOUT_DRIVER=typesense
TYPESENSE_API_KEY=masterKey
TYPESENSE_HOST=localhostLaravel Sail을 사용하는 경우, Docker 컨테이너 이름에 맞게 TYPESENSE_HOST 환경 변수를 조정해야 할 수 있습니다. 포트, 경로, 프로토콜도 선택적으로 지정할 수 있습니다.
TYPESENSE_PORT=8108
TYPESENSE_PATH=
TYPESENSE_PROTOCOL=httpTypesense 컬렉션에 대한 추가 설정 및 스키마 정의는 config/scout.php 설정 파일에서 확인할 수 있습니다. 자세한 내용은 Typesense 공식 문서를 참고하세요.
설정
검색 가능한 데이터 설정
기본적으로 모델의 toArray 결과 전체가 검색 인덱스에 저장됩니다. 인덱스에 동기화할 데이터를 직접 제어하고 싶다면, 모델에서 toSearchableArray 메서드를 오버라이드하세요.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* 모델의 인덱싱 가능한 데이터 배열을 반환합니다.
*
* @return array<string, mixed>
*/
public function toSearchableArray(): array
{
$array = $this->toArray();
// 데이터 배열을 원하는 대로 커스터마이징...
return $array;
}
}모델별 검색 엔진 설정
Scout는 기본적으로 scout 설정 파일에 지정된 기본 검색 엔진을 사용합니다. 특정 모델에 다른 엔진을 사용하고 싶다면, 모델에서 searchableUsing 메서드를 오버라이드하세요.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Engines\Engine;
use Laravel\Scout\Scout;
use Laravel\Scout\Searchable;
class User extends Model
{
use Searchable;
/**
* 이 모델 인덱싱에 사용할 엔진을 반환합니다.
*/
public function searchableUsing(): Engine
{
return Scout::engine('meilisearch');
}
}Database / Collection 엔진
Database 엔진
WARNING
Database 엔진은 현재 MySQL과 PostgreSQL만 지원합니다. 두 데이터베이스 모두 전체 텍스트 컬럼 인덱싱을 기본 제공합니다.
database 엔진은 MySQL / PostgreSQL의 전체 텍스트 인덱스와 LIKE 절을 사용하여 기존 데이터베이스를 직접 검색합니다. 외부 서비스나 별도 인프라 없이 검색 기능을 추가할 수 있는 가장 간단하고 실용적인 방법입니다.
database 엔진을 사용하려면 SCOUT_DRIVER 환경 변수를 database로 설정합니다.
SCOUT_DRIVER=database설정이 완료되면 검색 가능한 데이터를 정의하고 바로 검색 쿼리를 실행할 수 있습니다. 서드파티 엔진과 달리 별도의 인덱싱 작업 없이 데이터베이스 테이블을 직접 검색합니다.
데이터베이스 검색 전략 커스터마이징
기본적으로 database 엔진은 검색 가능하도록 설정된 모든 모델 속성에 LIKE 쿼리를 실행합니다. 특정 컬럼에 더 효율적인 검색 전략을 적용하려면 PHP 어트리뷰트를 활용할 수 있습니다.
SearchUsingFullText: 해당 컬럼에 데이터베이스 전체 텍스트 인덱스를 사용합니다.SearchUsingPrefix: 문자열 전체(%example%)가 아닌 앞부분만(example%) 검색하여 성능을 향상시킵니다.
이 어트리뷰트들은 모델의 toSearchableArray 메서드에 지정합니다. 어트리뷰트가 없는 컬럼은 기본 LIKE 전략을 계속 사용합니다.
use Laravel\Scout\Attributes\SearchUsingFullText;
use Laravel\Scout\Attributes\SearchUsingPrefix;
/**
* 모델의 인덱싱 가능한 데이터 배열을 반환합니다.
*
* @return array<string, mixed>
*/
#[SearchUsingPrefix(['id', 'email'])]
#[SearchUsingFullText(['bio'])]
public function toSearchableArray(): array
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'bio' => $this->bio,
];
}WARNING
특정 컬럼에 전체 텍스트 쿼리 조건을 사용하기 전에, 해당 컬럼에 전체 텍스트 인덱스가 설정되어 있는지 반드시 확인하세요.
Collection 엔진
"collection" 엔진은 빠른 프로토타이핑, 수백 건 수준의 매우 작은 데이터셋, 또는 테스트 실행 목적으로 설계되었습니다. 이 엔진은 데이터베이스에서 모든 레코드를 가져온 뒤 Laravel의 Str::is 헬퍼를 사용해 PHP에서 필터링하므로, 별도의 인덱싱이나 데이터베이스 특화 기능이 필요 없습니다. 실제 서비스 수준의 사용에는 database 엔진을 사용하는 것이 훨씬 적합합니다.
collection 엔진을 사용하려면 SCOUT_DRIVER 환경 변수를 collection으로 설정합니다.
SCOUT_DRIVER=collectioncollection 드라이버를 설정하면 별도의 인덱싱 작업 없이 바로 검색 쿼리를 실행할 수 있습니다. Algolia, Meilisearch, Typesense처럼 별도의 인덱스 초기화 작업이 필요하지 않습니다.
Database 엔진과의 차이점
database 엔진은 전체 텍스트 인덱스와 LIKE 절로 데이터베이스에서 직접 효율적으로 검색하는 반면, collection 엔진은 모든 레코드를 불러와 PHP에서 필터링합니다. collection 엔진은 SQLite, SQL Server를 포함한 Laravel 지원 모든 데이터베이스에서 동작하는 범용적인 옵션이지만, 데이터가 많아질수록 성능이 크게 떨어지므로 대용량 데이터에는 사용하지 않는 것이 좋습니다.
서드파티 엔진 설정
아래 설정 옵션들은 Algolia, Meilisearch, Typesense 같은 서드파티 검색 엔진을 사용할 때만 해당됩니다. database 엔진을 사용한다면 이 섹션을 건너뛰어도 됩니다.
모델 인덱스 설정
서드파티 엔진을 사용할 경우, 각 Eloquent 모델은 해당 모델의 모든 검색 가능 레코드를 담는 검색 "인덱스"와 동기화됩니다. 기본적으로 인덱스 이름은 모델의 테이블 이름(보통 모델명의 복수형)을 따릅니다. 인덱스 이름을 직접 지정하려면 모델에서 searchableAs 메서드를 오버라이드하세요.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
/**
* 모델과 연결된 인덱스 이름을 반환합니다.
*/
public function searchableAs(): string
{
return 'posts_index';
}
}NOTE
searchableAs 메서드는 database 엔진에서는 아무런 영향을 미치지 않습니다. database 엔진은 항상 모델의 데이터베이스 테이블을 직접 검색합니다.
모델 ID 설정
기본적으로 Scout는 모델의 기본 키(primary key)를 검색 인덱스의 고유 ID로 사용합니다. 서드파티 엔진에서 이 동작을 변경하려면 모델에서 getScoutKey와 getScoutKeyName 메서드를 오버라이드하세요.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
class User extends Model
{
use Searchable;
/**
* 모델 인덱싱에 사용할 값을 반환합니다.
*/
public function getScoutKey(): mixed
{
return $this->email;
}
/**
* 모델 인덱싱에 사용할 키 이름을 반환합니다.
*/
public function getScoutKeyName(): mixed
{
return 'email';
}
}NOTE
getScoutKey와 getScoutKeyName 메서드는 database 엔진에서는 아무런 영향을 미치지 않습니다. database 엔진은 항상 모델의 기본 키를 사용합니다.
Algolia
인덱스 설정
Algolia 인덱스에 필터링 가능한 속성, 랭킹, 패싯 등 추가 설정이 필요할 때, Algolia UI에서 직접 관리하는 대신 config/scout.php 파일에서 관리하면 배포 자동화 파이프라인에 포함시킬 수 있어 여러 환경 간 일관성을 유지하기 편합니다. 지원되는 모든 설정 항목을 자유롭게 구성할 수 있습니다.
config/scout.php의 algolia 설정 안에 각 인덱스별 설정을 추가합니다.
use App\Models\User;
use App\Models\Flight;
'algolia' => [
'id' => env('ALGOLIA_APP_ID', ''),
'secret' => env('ALGOLIA_SECRET', ''),
'index-settings' => [
User::class => [
'searchableAttributes' => ['id', 'name', 'email'],
'attributesForFaceting'=> ['filterOnly(email)'],
// 기타 설정 항목...
],
Flight::class => [
'searchableAttributes'=> ['id', 'destination'],
],
],
],소프트 삭제를 사용하는 모델이 index-settings 배열에 포함된 경우, Scout는 자동으로 해당 인덱스에 소프트 삭제 레코드의 패싯 필터링 지원을 추가합니다. 소프트 삭제 모델에 별도로 정의할 패싯 속성이 없다면 빈 항목만 추가해도 됩니다.
'index-settings' => [
Flight::class => []
],인덱스 설정을 마친 후에는 scout:sync-index-settings Artisan 명령을 실행하여 Algolia에 설정을 동기화해야 합니다. 이 명령을 배포 프로세스에 포함시키면 편리합니다.
php artisan scout:sync-index-settings사용자 식별
Scout를 사용하면 Algolia에서 인증된 사용자를 검색 작업에 자동으로 연결할 수 있습니다. Algolia 대시보드의 검색 분석을 볼 때 유용합니다. .env 파일에서 SCOUT_IDENTIFY 환경 변수를 true로 설정하면 활성화됩니다.
SCOUT_IDENTIFY=true이 기능을 활성화하면 요청 IP 주소와 인증된 사용자의 기본 식별자가 Algolia로 전달되어, 해당 사용자의 모든 검색 요청과 연결됩니다.
Meilisearch
인덱스 설정
Meilisearch는 where 메서드로 필터링할 속성(filterable attributes)이나 정렬에 사용할 속성(sortable attributes)을 미리 정의해야 합니다. 이 설정들은 config/scout.php의 meilisearch 항목 안에 index-settings로 지정합니다. 지원되는 모든 설정 항목을 활용할 수 있습니다.
use App\Models\User;
use App\Models\Flight;
'meilisearch' => [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY', null),
'index-settings' => [
User::class => [
'filterableAttributes'=> ['id', 'name', 'email'],
'sortableAttributes' => ['created_at'],
// 기타 설정 항목...
],
Flight::class => [
'filterableAttributes'=> ['id', 'destination'],
'sortableAttributes' => ['updated_at'],
],
],
],소프트 삭제를 사용하는 모델이 index-settings 배열에 포함된 경우, Scout는 자동으로 해당 인덱스에 소프트 삭제 레코드 필터링 지원을 추가합니다. 별도로 정의할 속성이 없다면 빈 항목만 추가해도 됩니다.
'index-settings' => [
Flight::class => []
],설정이 완료되면 scout:sync-index-settings Artisan 명령으로 Meilisearch에 동기화합니다. 배포 프로세스에 포함시키면 편리합니다.
php artisan scout:sync-index-settings검색 가능한 데이터 타입
Meilisearch에서 >, < 같은 필터 연산자는 올바른 데이터 타입에서만 작동합니다. 검색 가능한 데이터를 커스터마이징할 때 숫자 값은 반드시 적절한 타입으로 캐스팅해야 합니다.
public function toSearchableArray()
{
return [
'id' => (int) $this->id,
'name' => $this->name,
'price' => (float) $this->price,
];
}Typesense
검색 가능한 데이터 준비
Typesense를 사용할 경우, toSearchableArray 메서드에서 모델의 기본 키는 문자열로, 생성 일시는 UNIX 타임스탬프로 캐스팅해야 합니다.
/**
* 모델의 인덱싱 가능한 데이터 배열을 반환합니다.
*
* @return array<string, mixed>
*/
public function toSearchableArray(): array
{
return array_merge($this->toArray(),[
'id' => (string) $this->id,
'created_at' => $this->created_at->timestamp,
]);
}Typesense 컬렉션 스키마는 config/scout.php 파일에 정의합니다. 스키마는 Typesense에서 검색 가능한 각 필드의 데이터 타입을 지정합니다. 사용 가능한 모든 스키마 옵션은 [Typesense 공식 문서](https://typesense.