Precognition
번역일: 2026년 6월 25일
Precognition
소개
Laravel Precognition은 아직 실행되지 않은 HTTP 요청의 결과를 미리 예측할 수 있게 해주는 기능입니다. 가장 대표적인 활용 사례는 프론트엔드 JavaScript 애플리케이션에서 실시간 유효성 검사를 제공하는 것입니다. 백엔드에 이미 작성한 유효성 검사 규칙을 프론트엔드에 그대로 복사할 필요 없이, 서버의 규칙을 그대로 활용할 수 있습니다. Precognition은 특히 Laravel의 Inertia 기반 스타터 킷과 잘 어울립니다.
Laravel이 "사전 인식(precognitive) 요청"을 받으면, 해당 라우트의 모든 미들웨어를 실행하고 컨트롤러 의존성을 해결하며 폼 요청(Form Request) 유효성 검사까지 수행합니다. 단, 컨트롤러 메서드 자체는 실행하지 않습니다.
NOTE
쉽게 말해, Precognition 요청은 "컨트롤러 직전까지만 실행하는 드라이 런(dry-run)"입니다. 덕분에 실제 데이터를 저장하지 않고도 서버 유효성 검사 결과를 미리 받아볼 수 있습니다.
실시간 유효성 검사
Vue 사용하기
Laravel Precognition을 사용하면 Vue 프론트엔드에서 유효성 검사 규칙을 중복 작성하지 않고도 실시간 검사 기능을 구현할 수 있습니다. 새 사용자를 생성하는 폼을 예시로 살펴보겠습니다.
먼저, 라우트에 HandlePrecognitiveRequests 미들웨어를 추가하고, 유효성 검사 규칙을 담을 폼 요청(Form Request)을 생성합니다:
use App\Http\Requests\StoreUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (StoreUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);다음으로, Vue용 Precognition 프론트엔드 헬퍼를 NPM으로 설치합니다:
npm install laravel-precognition-vue패키지가 설치되면 Precognition의 useForm 함수를 사용해 폼 객체를 생성합니다. HTTP 메서드(post), 대상 URL(/users), 초기 폼 데이터를 인자로 전달합니다.
각 입력 필드의 change 이벤트에서 validate 메서드를 호출하면 실시간 유효성 검사가 활성화됩니다:
<script setup>
import { useForm } from 'laravel-precognition-vue';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = () => form.submit();
</script>
<template>
<form @submit.prevent="submit">
<label for="name">이름</label>
<input
id="name"
v-model="form.name"
@change="form.validate('name')"
/>
<div v-if="form.invalid('name')">
{{ form.errors.name }}
</div>
<label for="email">이메일</label>
<input
id="email"
type="email"
v-model="form.email"
@change="form.validate('email')"
/>
<div v-if="form.invalid('email')">
{{ form.errors.email }}
</div>
<button :disabled="form.processing">
사용자 생성
</button>
</form>
</template>사용자가 폼을 작성하면, Precognition이 라우트의 폼 요청에 정의된 유효성 검사 규칙을 기반으로 실시간 검사 결과를 제공합니다. 입력값이 변경될 때마다 디바운스(debounce)된 사전 인식 요청이 Laravel 애플리케이션으로 전송됩니다. 디바운스 대기 시간은 setValidationTimeout으로 조정할 수 있습니다:
form.setValidationTimeout(3000);유효성 검사 요청이 진행 중일 때는 validating 속성이 true가 됩니다:
<div v-if="form.validating">
검사 중...
</div>유효성 검사 요청 또는 폼 제출 시 반환된 오류는 자동으로 errors 객체에 채워집니다:
<div v-if="form.invalid('email')">
{{ form.errors.email }}
</div>폼에 오류가 하나라도 있는지 확인하려면 hasErrors 속성을 사용하세요:
<div v-if="form.hasErrors">
<!-- ... -->
</div>특정 입력 필드의 검사 통과/실패 여부는 valid와 invalid 함수로 확인할 수 있습니다:
<span v-if="form.valid('email')">
✅
</span>
<span v-else-if="form.invalid('email')">
❌
</span>WARNING
입력 필드의 유효/무효 상태는 값이 변경되고 유효성 검사 응답이 수신된 이후에만 표시됩니다.
Precognition으로 일부 입력 필드만 검사할 때는 오류를 수동으로 초기화하는 것이 유용할 수 있습니다. forgetError 함수를 사용하세요:
<input
id="avatar"
type="file"
@change="(e) => {
form.avatar = e.target.files[0]
form.forgetError('avatar')
}"
>폼 제출 응답에 따라 추가 동작을 실행할 수도 있습니다. submit 함수는 Axios 요청 프로미스를 반환하므로, 성공 시 폼을 초기화하거나 실패 시 오류를 처리할 수 있습니다:
const submit = () => form.submit()
.then(response => {
form.reset();
alert('사용자가 생성되었습니다.');
})
.catch(error => {
alert('오류가 발생했습니다.');
});폼 제출 요청이 진행 중인지 확인하려면 processing 속성을 확인하세요:
<button :disabled="form.processing">
제출
</button>Vue와 Inertia 사용하기
NOTE
Vue와 Inertia로 Laravel 애플리케이션을 빠르게 시작하려면 스타터 킷 사용을 고려해보세요. 스타터 킷은 백엔드와 프론트엔드 인증 스캐폴딩을 제공합니다.
Inertia 환경에서 Precognition을 사용하기 전에, 먼저 Vue에서 Precognition 사용하기 문서를 참고하세요. Vue와 Inertia를 함께 사용할 때는 Inertia 호환 Precognition 라이브러리를 설치해야 합니다:
npm install laravel-precognition-vue-inertia설치 후, useForm 함수는 위에서 설명한 유효성 검사 기능이 추가된 Inertia 폼 헬퍼를 반환합니다.
이 버전의 submit 메서드는 HTTP 메서드나 URL을 별도로 지정할 필요가 없습니다. 대신 Inertia의 visit 옵션을 첫 번째 인자로 전달합니다. 또한 submit 메서드는 Promise를 반환하지 않으며, 대신 visit 옵션 안에 Inertia의 이벤트 콜백을 제공할 수 있습니다:
<script setup>
import { useForm } from 'laravel-precognition-vue-inertia';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = () => form.submit({
preserveScroll: true,
onSuccess: () => form.reset(),
});
</script>React 사용하기
Laravel Precognition을 사용하면 React 프론트엔드에서도 유효성 검사 규칙을 중복 작성하지 않고 실시간 검사 기능을 구현할 수 있습니다. 새 사용자를 생성하는 폼을 예시로 살펴보겠습니다.
먼저, 라우트에 HandlePrecognitiveRequests 미들웨어를 추가하고 폼 요청을 생성합니다:
use App\Http\Requests\StoreUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (StoreUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);다음으로, React용 Precognition 프론트엔드 헬퍼를 NPM으로 설치합니다:
npm install laravel-precognition-react패키지가 설치되면 useForm 함수로 폼 객체를 생성합니다. React에서는 change 이벤트에서 setData로 값을 업데이트하고, blur 이벤트에서 validate를 호출해 실시간 검사를 활성화합니다:
import { useForm } from 'laravel-precognition-react';
export default function Form() {
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = (e) => {
e.preventDefault();
form.submit();
};
return (
<form onSubmit={submit}>
<label for="name">이름</label>
<input
id="name"
value={form.data.name}
onChange={(e) => form.setData('name', e.target.value)}
onBlur={() => form.validate('name')}
/>
{form.invalid('name') && <div>{form.errors.name}</div>}
<label for="email">이메일</label>
<input
id="email"
value={form.data.email}
onChange={(e) => form.setData('email', e.target.value)}
onBlur={() => form.validate('email')}
/>
{form.invalid('email') && <div>{form.errors.email}</div>}
<button disabled={form.processing}>
사용자 생성
</button>
</form>
);
};NOTE
Vue와 달리 React에서는 blur 이벤트(포커스 이탈)에서 validate를 호출하는 패턴이 일반적입니다. 사용자가 입력을 완료하고 다음 필드로 이동할 때 검사가 시작됩니다.
사용자가 폼을 작성하면, 폼 요청의 유효성 검사 규칙을 기반으로 실시간 검사 결과를 제공합니다. 디바운스 대기 시간은 setValidationTimeout으로 조정할 수 있습니다:
form.setValidationTimeout(3000);유효성 검사 요청이 진행 중일 때는 validating 속성이 true가 됩니다:
{form.validating && <div>검사 중...</div>}오류는 자동으로 errors 객체에 채워집니다:
{form.invalid('email') && <div>{form.errors.email}</div>}폼에 오류가 있는지 확인하려면 hasErrors 속성을 사용하세요:
{form.hasErrors && <div><!-- ... --></div>}특정 필드의 검사 통과/실패 여부는 valid와 invalid 함수로 확인할 수 있습니다:
{form.valid('email') && <span>✅</span>}
{form.invalid('email') && <span>❌</span>}WARNING
입력 필드의 유효/무효 상태는 값이 변경되고 유효성 검사 응답이 수신된 이후에만 표시됩니다.
일부 필드의 오류를 수동으로 초기화할 때는 forgetError 함수를 사용하세요:
<input
id="avatar"
type="file"
onChange={(e) => {
form.setData('avatar', e.target.value);
form.forgetError('avatar');
}}
>폼 제출 응답에 따른 추가 처리도 가능합니다. submit 함수는 Axios 요청 프로미스를 반환합니다:
const submit = (e) => {
e.preventDefault();
form.submit()
.then(response => {
form.reset();
alert('사용자가 생성되었습니다.');
})
.catch(error => {
alert('오류가 발생했습니다.');
});
};폼 제출 요청 진행 여부는 processing 속성으로 확인합니다:
<button disabled={form.processing}>
제출
</button>React와 Inertia 사용하기
NOTE
React와 Inertia로 Laravel 애플리케이션을 빠르게 시작하려면 스타터 킷 사용을 고려해보세요. 스타터 킷은 백엔드와 프론트엔드 인증 스캐폴딩을 제공합니다.
Inertia 환경에서 Precognition을 사용하기 전에, 먼저 React에서 Precognition 사용하기 문서를 참고하세요. React와 Inertia를 함께 사용할 때는 Inertia 호환 Precognition 라이브러리를 설치해야 합니다:
npm install laravel-precognition-react-inertia설치 후, useForm 함수는 유효성 검사 기능이 추가된 Inertia 폼 헬퍼를 반환합니다.
submit 메서드는 HTTP 메서드나 URL을 별도로 지정할 필요 없이, Inertia의 visit 옵션을 첫 번째 인자로 전달합니다. Promise를 반환하지 않으며, 대신 Inertia의 이벤트 콜백을 visit 옵션 안에서 사용할 수 있습니다:
import { useForm } from 'laravel-precognition-react-inertia';
const form = useForm('post', '/users', {
name: '',
email: '',
});
const submit = (e) => {
e.preventDefault();
form.submit({
preserveScroll: true,
onSuccess: () => form.reset(),
});
};Alpine과 Blade 사용하기
Laravel Precognition을 사용하면 Alpine.js 기반 프론트엔드에서도 유효성 검사 규칙 중복 없이 실시간 검사 기능을 구현할 수 있습니다.
먼저, 라우트에 HandlePrecognitiveRequests 미들웨어를 추가하고 폼 요청을 생성합니다:
use App\Http\Requests\CreateUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
Route::post('/users', function (CreateUserRequest $request) {
// ...
})->middleware([HandlePrecognitiveRequests::class]);다음으로, Alpine용 Precognition 프론트엔드 헬퍼를 NPM으로 설치합니다:
npm install laravel-precognition-alpine그런 다음 resources/js/app.js 파일에서 Alpine에 Precognition 플러그인을 등록합니다:
import Alpine from 'alpinejs';
import Precognition from 'laravel-precognition-alpine';
window.Alpine = Alpine;
Alpine.plugin(Precognition);
Alpine.start();패키지 설치 및 등록이 완료되면 Precognition의 $form 매직을 사용해 폼 객체를 생성할 수 있습니다. HTTP 메서드(post), 대상 URL(/users), 초기 폼 데이터를 인자로 전달합니다.
각 입력 필드에 폼 데이터를 바인딩하고 change 이벤트에서 validate 메서드를 호출해 실시간 검사를 활성화합니다:
<form x-data="{
form: $form('post', '/register', {
name: '',
email: '',
}),
}">
@csrf
<label for="name">이름</label>
<input
id="name"
name="name"
x-model="form.name"
@change="form.validate('name')"
/>
<template x-if="form.invalid('name')">
<div x-text="form.errors.name"></div>
</template>
<label for="email">이메일</label>
<input
id="email"
name="email"
x-model="form.email"
@change="form.validate('email')"
/>
<template x-if="form.invalid('email')">
<div x-text="form.errors.email"></div>
</template>
<button :disabled="form.processing">
사용자 생성
</button>
</form>사용자가 폼을 작성하면, 폼 요청의 유효성 검사 규칙을 기반으로 실시간 검사 결과를 제공합니다. 디바운스 대기 시간은 setValidationTimeout으로 조정할 수 있습니다:
form.setValidationTimeout(3000);유효성 검사 요청이 진행 중일 때는 validating 속성이 true가 됩니다:
<template x-if="form.validating">
<div>검사 중...</div>
</template>오류는 자동으로 errors 객체에 채워집니다:
<template x-if="form.invalid('email')">
<div x-text="form.errors.email"></div>
</template>폼에 오류가 있는지 확인하려면 hasErrors 속성을 사용하세요:
<template x-if="form.hasErrors">
<div><!-- ... --></div>
</template>특정 필드의 검사 통과/실패 여부는 valid와 invalid 함수로 확인할 수 있습니다:
<template x-if="form.valid('email')">
<span>✅</span>
</template>
<template x-if="form.invalid('email')">
<span>❌</span>
</template>WARNING
입력 필드의 유효/무효 상태는 값이 변경되고 유효성 검사 응답이 수신된 이후에만 표시됩니다.
폼 제출 요청 진행 여부는 processing 속성으로 확인합니다:
<button :disabled="form.processing">
제출
</button>이전 폼 데이터 복원
위의 사용자 생성 예시는 Precognition으로 실시간 검사를 수행하면서도 전통적인 서버 사이드 폼 제출 방식을 사용합니다. 이 경우 서버 사이드 폼 제출 후 반환된 이전 입력값과 유효성 검사 오류를 폼에 채워야 합니다:
<form x-data="{
form: $form('post', '/register', {
name: '{{ old('name') }}',
email: '{{ old('email') }}',
}).setErrors({{ Js::from($errors->messages()) }}),
}">XHR 방식으로 폼을 제출하려면 submit 함수를 사용하세요. 이 함수는 Axios 요청 프로미스를 반환합니다:
<form
x-data="{
form: $form('post', '/register', {
name: '',
email: '',
}),
submit() {
this.form.submit()
.then(response => {
form.reset();
alert('사용자가 생성되었습니다.')
})
.catch(error => {
alert('오류가 발생했습니다.');
});
},
}"
@submit.prevent="submit"
>Axios 설정하기
Precognition 유효성 검사 라이브러리는 내부적으로 Axios HTTP 클라이언트를 사용해 백엔드로 요청을 보냅니다. 필요한 경우 Axios 인스턴스를 커스터마이징할 수 있습니다. 예를 들어, laravel-precognition-vue 라이브러리를 사용할 때 resources/js/app.js 파일에서 모든 요청에 공통 헤더를 추가할 수 있습니다:
import { client } from 'laravel-precognition-vue';
client.axios().defaults.headers.common['Authorization'] = authToken;애플리케이션에 이미 설정된 Axios 인스턴스가 있다면, Precognition이 해당 인스턴스를 사용하도록 지정할 수도 있습니다:
import Axios from 'axios';
import { client } from 'laravel-precognition-vue';
window.axios = Axios.create()
window.axios.defaults.headers.common['Authorization'] = authToken;
client.use(window.axios)WARNING
Inertia 전용 Precognition 라이브러리는 유효성 검사 요청에만 설정된 Axios 인스턴스를 사용합니다. 폼 제출은 항상 Inertia가 처리합니다.
유효성 검사 규칙 커스터마이징
사전 인식 요청에서 실행되는 유효성 검사 규칙은 요청 객체의 isPrecognitive 메서드를 사용해 커스터마이징할 수 있습니다.
예를 들어, 사용자 생성 폼에서 비밀번호가 "유출되지 않은(uncompromised)" 비밀번호인지 검사하는 규칙은 최종 폼 제출 시에만 실행하고, 사전 인식 요청에서는 필수 입력과 최소 길이(8자)만 검사하도록 설정할 수 있습니다:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Password;
class StoreUserRequest extends FormRequest
{
/**
* 요청에 적용할 유효성 검사 규칙을 반환합니다.
*
* @return array
*/
protected function rules()
{
return [
'password' => [
'required',
$this->isPrecognitive()
? Password::min(8)
: Password::min(8)->uncompromised(),
],
// ...
];
}
}파일 업로드 처리
기본적으로 Laravel Precognition은 사전 인식 유효성 검사 요청 중에 파일을 업로드하거나 검사하지 않습니다. 대용량 파일이 불필요하게 여러 번 업로드되는 것을 방지하기 위해서입니다.
따라서 파일 필드의 required 규칙은 실제 폼 제출 시에만 적용되도록 유효성 검사 규칙을 커스터마이징해야 합니다:
/**
* 요청에 적용할 유효성 검사 규칙을 반환합니다.
*
* @return array
*/
protected function rules()
{
return [
'avatar' => [
...$this->isPrecognitive() ? [] : ['required'],
'image',
'mimes:jpg,png',
'dimensions:ratio=3/2',
],
// ...
];
}모든 유효성 검사 요청에 파일을 포함하고 싶다면, 클라이언트 측 폼 인스턴스에서 validateFiles 함수를 호출하세요:
form.validateFiles();부수 효과 관리
라우트에 HandlePrecognitiveRequests 미들웨어를 추가할 때는 다른 미들웨어에서 사전 인식 요청 중에 건너뛰어야 할 부수 효과가 있는