본문 바로가기

Precognition

업데이트됨

번역일: 2026년 10월 3일

이 페이지는 원문이 업데이트되어 번역이 갱신되었습니다.

원문 수정
2026년 10월 3일
번역 갱신
2026년 10월 3일

Precognition

소개

Laravel Precognition을 사용하면 실제로 실행되기 전에 HTTP 요청의 결과를 미리 예측할 수 있습니다. Precognition의 대표적인 활용 사례는 프론트엔드 JavaScript 애플리케이션에서 백엔드의 유효성 검증 규칙을 중복 작성하지 않고도 "실시간" 유효성 검증 경험을 제공하는 것입니다.

Laravel이 "precognitive 요청(선제 요청)"을 받으면, 해당 라우트의 미들웨어를 모두 실행하고 폼 리퀘스트 유효성 검증을 포함해 컨트롤러 의존성을 모두 해석(resolve)합니다. 다만 실제로 라우트의 컨트롤러 메서드는 실행하지 않습니다.

NOTE

Inertia 2.3부터는 Precognition 지원이 기본으로 내장되어 있습니다. 자세한 내용은 Inertia Forms 문서를 참고하세요. Inertia 2.3 이전 버전에서는 Precognition 0.x가 필요합니다.

실시간 유효성 검증

Vue 사용하기

Laravel Precognition을 사용하면 Vue 프론트엔드 애플리케이션에서 유효성 검증 규칙을 중복 작성하지 않고도 사용자에게 실시간 유효성 검증 경험을 제공할 수 있습니다. 동작 방식을 살펴보기 위해, 새 사용자를 생성하는 폼을 만들어 보겠습니다.

먼저, 특정 라우트에서 Precognition을 활성화하려면 라우트 정의에 HandlePrecognitiveRequests 미들웨어를 추가해야 합니다. 또한 해당 라우트의 유효성 검증 규칙을 담을 폼 리퀘스트도 생성해야 합니다.

use App\Http\Requests\StoreUserRequest; use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests; Route::post('/users', function (StoreUserRequest $request) { // ... })->middleware([HandlePrecognitiveRequests::class]);

다음으로, NPM을 통해 Vue용 Laravel Precognition 프론트엔드 헬퍼를 설치합니다.

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">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">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"> Create User </button> </form> </template>

이제 사용자가 폼을 입력하면, 라우트의 폼 리퀘스트에 정의된 유효성 검증 규칙을 바탕으로 Precognition이 실시간 검증 결과를 제공합니다. 입력 필드 값이 변경될 때마다 디바운스(debounce) 처리된 "precognitive" 유효성 검증 요청이 Laravel 애플리케이션으로 전송됩니다. 폼의 setValidationTimeout 함수를 호출하면 디바운스 지연 시간을 조정할 수 있습니다.

form.setValidationTimeout(3000);

유효성 검증 요청이 진행 중일 때는 폼의 validating 속성 값이 true가 됩니다.

<div v-if="form.validating"> 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') }" >

지금까지 살펴본 것처럼 change 이벤트에 훅을 걸어 사용자가 입력 필드를 조작할 때마다 개별적으로 검증할 수 있습니다. 하지만 사용자가 아직 조작하지 않은 입력 필드까지 검증해야 하는 경우도 있습니다. 예를 들어 여러 단계로 구성된 "마법사(wizard)" 폼에서 다음 단계로 넘어가기 전에, 사용자가 건드렸는지 여부와 상관없이 현재 화면에 보이는 모든 입력 필드를 검증하고 싶은 경우가 대표적입니다.

Precognition에서 이를 처리하려면 validate 메서드를 호출하면서 검증하려는 필드 이름들을 only 설정 키에 전달하면 됩니다. 검증 결과는 onSuccess 또는 onValidationError 콜백으로 처리할 수 있습니다.

<button type="button" @click="form.validate({ only: ['name', 'email', 'phone'], onSuccess: (response) => nextStep(), onValidationError: (response) => /* ... */, })" >Next Step</button>

물론 폼 제출 응답에 반응해 코드를 실행할 수도 있습니다. 폼의 submit 함수는 Axios 요청 프로미스(promise)를 반환합니다. 이를 이용하면 응답 페이로드에 접근하거나, 제출 성공 시 폼 입력값을 초기화하거나, 요청 실패를 처리하는 등의 작업을 편리하게 수행할 수 있습니다.

const submit = () => form.submit() .then(response => { form.reset(); alert('User created.'); }) .catch(error => { alert('An error occurred.'); });

폼 제출 요청이 진행 중인지는 폼의 processing 속성으로 확인할 수 있습니다.

<button :disabled="form.processing"> Submit </button>

React 사용하기

Laravel Precognition을 사용하면 React 프론트엔드 애플리케이션에서 유효성 검증 규칙을 중복 작성하지 않고도 사용자에게 실시간 유효성 검증 경험을 제공할 수 있습니다. 동작 방식을 살펴보기 위해, 새 사용자를 생성하는 폼을 만들어 보겠습니다.

먼저, 특정 라우트에서 Precognition을 활성화하려면 라우트 정의에 HandlePrecognitiveRequests 미들웨어를 추가해야 합니다. 또한 해당 라우트의 유효성 검증 규칙을 담을 폼 리퀘스트도 생성해야 합니다.

use App\Http\Requests\StoreUserRequest; use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests; Route::post('/users', function (StoreUserRequest $request) { // ... })->middleware([HandlePrecognitiveRequests::class]);

다음으로, NPM을 통해 React용 Laravel Precognition 프론트엔드 헬퍼를 설치합니다.

npm install laravel-precognition-react

패키지 설치가 끝나면 Precognition의 useForm 함수를 사용해 폼 객체를 생성할 수 있습니다. 이때 HTTP 메서드(post), 대상 URL(/users), 초기 폼 데이터를 전달합니다.

실시간 유효성 검증을 활성화하려면 각 입력 필드의 change와 blur 이벤트를 수신해야 합니다. 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 htmlFor="name">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 htmlFor="email">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}> Create User </button> </form> ); };

이제 사용자가 폼을 입력하면, 라우트의 폼 리퀘스트에 정의된 유효성 검증 규칙을 바탕으로 Precognition이 실시간 검증 결과를 제공합니다. 입력 필드 값이 변경될 때마다 디바운스 처리된 "precognitive" 유효성 검증 요청이 Laravel 애플리케이션으로 전송됩니다. 폼의 setValidationTimeout 함수를 호출하면 디바운스 지연 시간을 조정할 수 있습니다.

form.setValidationTimeout(3000);

유효성 검증 요청이 진행 중일 때는 폼의 validating 속성 값이 true가 됩니다.

{form.validating && <div>Validating...</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

입력 필드는 값이 변경되고 유효성 검증 응답을 받은 이후에만 유효/무효 상태로 표시됩니다.

Precognition으로 폼 입력값 중 일부만 유효성 검증하는 경우, 오류를 수동으로 지워야 할 때가 있습니다. 이때는 폼의 forgetError 함수를 사용하면 됩니다.

<input id="avatar" type="file" onChange={(e) => { form.setData('avatar', e.target.files[0]); form.forgetError('avatar'); }} >

지금까지 살펴본 것처럼 blur 이벤트에 훅을 걸어 사용자가 입력 필드를 조작할 때마다 개별적으로 검증할 수 있습니다. 하지만 사용자가 아직 조작하지 않은 입력 필드까지 검증해야 하는 경우도 있습니다. 예를 들어 여러 단계로 구성된 "마법사(wizard)" 폼에서 다음 단계로 넘어가기 전에, 사용자가 건드렸는지 여부와 상관없이 현재 화면에 보이는 모든 입력 필드를 검증하고 싶은 경우가 대표적입니다.

Precognition에서 이를 처리하려면 validate 메서드를 호출하면서 검증하려는 필드 이름들을 only 설정 키에 전달하면 됩니다. 검증 결과는 onSuccess 또는 onValidationError 콜백으로 처리할 수 있습니다.

<button type="button" onClick={() => form.validate({ only: ['name', 'email', 'phone'], onSuccess: (response) => nextStep(), onValidationError: (response) => /* ... */, })} >Next Step</button>

물론 폼 제출 응답에 반응해 코드를 실행할 수도 있습니다. 폼의 submit 함수는 Axios 요청 프로미스를 반환합니다. 이를 이용하면 응답 페이로드에 접근하거나, 제출 성공 시 폼 입력값을 초기화하거나, 요청 실패를 처리하는 등의 작업을 편리하게 수행할 수 있습니다.

const submit = (e) => { e.preventDefault(); form.submit() .then(response => { form.reset(); alert('User created.'); }) .catch(error => { alert('An error occurred.'); }); };

폼 제출 요청이 진행 중인지는 폼의 processing 속성으로 확인할 수 있습니다.

<button disabled={form.processing}> Submit </button>

Alpine과 Blade 사용하기

Laravel Precognition을 사용하면 Alpine 프론트엔드 애플리케이션에서 유효성 검증 규칙을 중복 작성하지 않고도 사용자에게 실시간 유효성 검증 경험을 제공할 수 있습니다. 동작 방식을 살펴보기 위해, 새 사용자를 생성하는 폼을 만들어 보겠습니다.

먼저, 특정 라우트에서 Precognition을 활성화하려면 라우트 정의에 HandlePrecognitiveRequests 미들웨어를 추가해야 합니다. 또한 해당 라우트의 유효성 검증 규칙을 담을 폼 리퀘스트도 생성해야 합니다.

use App\Http\Requests\CreateUserRequest; use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests; Route::post('/users', function (CreateUserRequest $request) { // ... })->middleware([HandlePrecognitiveRequests::class]);

다음으로, NPM을 통해 Alpine용 Laravel Precognition 프론트엔드 헬퍼를 설치합니다.

npm install laravel-precognition-alpine

그런 다음 resources/js/app.js 파일에서 Precognition 플러그인을 Alpine에 등록합니다.

import Alpine from 'alpinejs'; import Precognition from 'laravel-precognition-alpine'; window.Alpine = Alpine; Alpine.plugin(Precognition); Alpine.start();

패키지 설치와 등록이 끝나면, Precognition의 $form "매직(magic)"을 사용해 폼 객체를 생성할 수 있습니다. 이때 HTTP 메서드(post), 대상 URL(/users), 초기 폼 데이터를 전달합니다.

실시간 유효성 검증을 활성화하려면 폼 데이터를 각 입력 필드에 바인딩한 뒤, 각 입력 필드의 change 이벤트를 수신해야 합니다. change 이벤트 핸들러에서는 입력 필드 이름을 인자로 전달해 폼의 validate 메서드를 호출합니다.

<form x-data="{ form: $form('post', '/register', { name: '', email: '', }), }"> @csrf <label for="name">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">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"> Create User </button> </form>

이제 사용자가 폼을 입력하면, 라우트의 폼 리퀘스트에 정의된 유효성 검증 규칙을 바탕으로 Precognition이 실시간 검증 결과를 제공합니다. 입력 필드 값이 변경될 때마다 디바운스 처리된 "precognitive" 유효성 검증 요청이 Laravel 애플리케이션으로 전송됩니다. 폼의 setValidationTimeout 함수를 호출하면 디바운스 지연 시간을 조정할 수 있습니다.

form.setValidationTimeout(3000);

유효성 검증 요청이 진행 중일 때는 폼의 validating 속성 값이 true가 됩니다.

<template x-if="form.validating"> <div>Validating...</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

입력 필드는 값이 변경되고 유효성 검증 응답을 받은 이후에만 유효/무효 상태로 표시됩니다.

지금까지 살펴본 것처럼 change 이벤트에 훅을 걸어 사용자가 입력 필드를 조작할 때마다 개별적으로 검증할 수 있습니다. 하지만 사용자가 아직 조작하지 않은 입력 필드까지 검증해야 하는 경우도 있습니다. 예를 들어 여러 단계로 구성된 "마법사(wizard)" 폼에서 다음 단계로 넘어가기 전에, 사용자가 건드렸는지 여부와 상관없이 현재 화면에 보이는 모든 입력 필드를 검증하고 싶은 경우가 대표적입니다.

Precognition에서 이를 처리하려면 validate 메서드를 호출하면서 검증하려는 필드 이름들을 only 설정 키에 전달하면 됩니다. 검증 결과는 onSuccess 또는 onValidationError 콜백으로 처리할 수 있습니다.

<button type="button" @click="form.validate({ only: ['name', 'email', 'phone'], onSuccess: (response) => nextStep(), onValidationError: (response) => /* ... */, })" >Next Step</button>

폼 제출 요청이 진행 중인지는 폼의 processing 속성으로 확인할 수 있습니다.

<button :disabled="form.processing"> Submit </button>

이전 폼 데이터 다시 채우기

앞서 살펴본 사용자 생성 예제에서는 Precognition으로 실시간 유효성 검증을 수행하면서도, 실제 폼 제출은 전통적인 서버 사이드 방식으로 처리하고 있습니다. 따라서 서버 사이드 폼 제출에서 반환된 "이전" 입력값과 유효성 검증 오류를 폼에 다시 채워 넣어야 합니다.

<form x-data="{ form: $form('post', '/register', { name: '{{ old('name') }}', email: '{{ old('email') }}', }).setErrors({{ Js::from($errors->messages()) }}), }">

반대로 폼을 XHR 방식으로 제출하고 싶다면, Axios 요청 프로미스를 반환하는 폼의 submit 함수를 사용할 수 있습니다.

<form x-data="{ form: $form('post', '/register', { name: '', email: '', }), submit() { this.form.submit() .then(response => { this.form.reset(); alert('User created.') }) .catch(error => { alert('An error occurred.'); }); }, }" @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)

배열 유효성 검증

와일드카드를 사용하면 배열이나 중첩 객체 내부의 필드를 검증할 수 있습니다. *는 경로의 한 단계(segment)를 의미합니다.

// 배열 내 모든 사용자의 email 필드를 검증... form.validate('users.*.email'); // profile 객체의 모든 필드를 검증... form.validate('profile.*'); // 모든 사용자의 모든 필드를 검증... form.validate('users.*.*');

유효성 검증 규칙 커스터마이징

요청의 isPrecognitive 메서드를 활용하면 precognitive 요청에서 실행되는 유효성 검증 규칙을 다르게 설정할 수 있습니다.

예를 들어 사용자 생성 폼에서, 비밀번호가 "유출된 적이 없는지(uncompromised)" 검사하는 규칙은 최종 폼 제출 시에만 적용하고 싶을 수 있습니다. precognitive 유효성 검증 요청에서는 비밀번호가 필수이고 최소 8자 이상인지만 검증하도록 하겠습니다. isPrecognitive 메서드를 사용하면 폼 리퀘스트에 정의된 규칙을 다음과 같이 상황에 맞게 조정할 수 있습니다.

<?php namespace App\Http\Requests; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rules\Password; class StoreUserRequest extends FormRequest { /** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'password' => [ 'required', $this->isPrecognitive() ? Password::min(8) : Password::min(8)->uncompromised(), ], // ... ]; } }

파일 업로드 처리

Laravel Precognition은 기본적으로 precognitive 유효성 검증 요청에서 파일을 업로드하거나 검증하지 않습니다. 이는 큰 용량의 파일이 불필요하게 여러 번 업로드되는 것을 방지하기 위함입니다.

이러한 동작 방식 때문에, 해당 필드가 전체 폼 제출 시에만 필수가 되도록 폼 리퀘스트의 유효성 검증 규칙을 커스터마이징해 두어야 합니다.

/** * Get the validation rules that apply to the request. * * @return array */ public function rules() { return [ 'avatar' => [ ...$this->isPrecognitive() ? [] : ['required'], 'image', 'mimes:jpg,png', 'dimensions:ratio=3/2', ], // ... ]; }

만약 모든 유효성 검증 요청에 파일을 포함시키고 싶다면, 클라이언트 측 폼 인스턴스에서 validateFiles 함수를 호출하면 됩니다.

form.validateFiles();

부수 효과 관리

라우트에 HandlePrecognitiveRequests 미들웨어를 추가할 때는, precognitive 요청 동안 건너뛰어야 할 부수 효과(side-effect)가 다른 미들웨어에 있지는 않은지 함께 검토해야 합니다.

예를 들어 사용자가 애플리케이션과 상호작용한 총 횟수를 집계하는 미들웨어가 있다고 가정해 봅시다. 이때 precognitive 요청은 실제 상호작용으로 집계하고 싶지 않을 수 있습니다. 이런 경우 요청의 isPrecognitive 메서드를 확인한 뒤에 상호작용 횟수를 증가시키면 됩니다.

<?php namespace App\Http\Middleware; use App\Facades\Interaction; use Closure; use Illuminate\Http\Request; class InteractionMiddleware { /** * Handle an incoming request. */ public function handle(Request $request, Closure $next): mixed { if (! $request->isPrecognitive()) { Interaction::incrementFor($request->user()); } return $next($request); } }

테스트

테스트 코드에서 precognitive 요청을 보내고 싶다면, Laravel의 TestCase에 포함된 withPrecognition 헬퍼를 사용할 수 있습니다. 이 헬퍼는 Precognition 요청 헤더를 자동으로 추가해 줍니다.

또한 precognitive 요청이 성공적으로 처리됐는지(즉, 유효성 검증 오류가 반환되지 않았는지) 검증하고 싶다면, 응답(response)의 assertSuccessfulPrecognition 메서드를 사용할 수 있습니다.

Pest

it('validates registration form with precognition', function () { $response = $this->withPrecognition() ->post('/register', [ 'name' => 'Taylor Otwell', ]); $response->assertSuccessfulPrecognition(); expect(User::count())->toBe(0); });

PHPUnit

public function test_it_validates_registration_form_with_precognition() { $response = $this->withPrecognition() ->post('/register', [ 'name' => 'Taylor Otwell', ]); $response->assertSuccessfulPrecognition(); $this->assertSame(0, User::count()); }

이 문서는 Laravel 공식 문서(MIT)를 한국 개발자를 위해 번역·재구성한 것입니다.

번역일: 2026년 10월 3일