Precognition

번역일: 2026년 6월 25일

Precognition

소개

Laravel Precognition은 아직 실행되지 않은 HTTP 요청의 결과를 미리 예측할 수 있게 해주는 기능입니다. 가장 대표적인 활용 사례는 프론트엔드 JavaScript 애플리케이션에서 실시간(live) 유효성 검사를 제공하는 것입니다. 백엔드의 유효성 검사 규칙을 프론트엔드에 중복으로 작성할 필요 없이, 백엔드 규칙 하나만으로 실시간 피드백을 제공할 수 있습니다. Precognition은 특히 Inertia 기반의 스타터 킷과 잘 어울립니다.

Laravel이 "사전 인식(precognitive)" 요청을 수신하면, 해당 라우트의 모든 미들웨어를 실행하고 컨트롤러 의존성을 주입하며 폼 리퀘스트 유효성 검사까지 수행합니다. 단, 컨트롤러 메서드 자체는 실행하지 않습니다.

동작 요약: Precognition 요청 = 미들웨어 + 유효성 검사 실행, 컨트롤러 로직은 실행하지 않음.

실시간 유효성 검사

Vue 사용하기

Laravel Precognition을 활용하면 Vue 애플리케이션에서 유효성 검사 규칙을 중복 작성하지 않고도 실시간 유효성 검사를 제공할 수 있습니다. 예시로 신규 사용자 생성 폼을 만들어 보겠습니다.

먼저, 해당 라우트에 HandlePrecognitiveRequests 미들웨어를 추가합니다. 유효성 검사 규칙은 폼 리퀘스트에 정의합니다:

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

다음으로 NPM을 통해 Vue용 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">이름</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') }" >

사용자가 아직 상호작용하지 않은 필드를 유효성 검사해야 할 경우도 있습니다. 예를 들어 단계별 "마법사(wizard)" 폼에서 다음 단계로 넘어가기 전, 현재 화면에 보이는 모든 필드를 일괄 검사하고 싶을 때입니다. 이럴 때는 validate 메서드에 only 옵션으로 검사할 필드명을 전달하고, onSuccess/onValidationError 콜백으로 결과를 처리합니다:

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

폼 제출 결과에 따른 후속 처리도 가능합니다. 폼의 submit 함수는 Axios 요청 Promise를 반환하므로, 제출 성공 시 폼 초기화나 실패 처리를 체이닝으로 구현할 수 있습니다:

const submit = () => form.submit() .then(response => { form.reset(); alert('사용자가 생성되었습니다.'); }) .catch(error => { alert('오류가 발생했습니다.'); });

폼 제출 요청이 진행 중인지는 processing 속성으로 확인합니다:

<button :disabled="form.processing"> 제출 </button>

Vue와 Inertia 사용하기

NOTE

Vue와 Inertia로 Laravel 애플리케이션을 빠르게 시작하고 싶다면 스타터 킷 사용을 고려해 보세요. 스타터 킷은 백엔드와 프론트엔드 인증 스캐폴딩을 함께 제공합니다.

Vue와 Inertia 조합에서 Precognition을 사용하기 전에, 먼저 Vue에서 Precognition 사용하기 섹션을 읽어보세요. Inertia와 함께 사용할 때는 전용 패키지를 NPM으로 설치해야 합니다:

npm install laravel-precognition-vue-inertia

설치 후 useForm 함수는 위에서 설명한 유효성 검사 기능이 추가된 Inertia 폼 헬퍼를 반환합니다.

Inertia 버전의 submit 메서드는 HTTP 메서드와 URL을 별도로 지정할 필요가 없습니다. 대신 Inertia의 visit 옵션을 인자로 전달합니다. 또한 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]);

다음으로 NPM을 통해 React용 Precognition 헬퍼를 설치합니다:

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 htmlFor="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">이메일</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> ); };

사용자가 폼을 작성하면, Precognition은 폼 리퀘스트의 유효성 검사 규칙을 기반으로 실시간 검사 결과를 제공합니다. 디바운스 지연 시간은 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'); }} >

단계별 마법사 폼처럼 사용자가 아직 상호작용하지 않은 필드를 일괄 검사해야 할 때는 validate 메서드에 only 옵션을 전달합니다:

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

폼 제출은 Axios Promise를 반환하므로 다음과 같이 후속 처리를 작성합니다:

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로 빠르게 시작하고 싶다면 스타터 킷 사용을 고려해 보세요. 스타터 킷은 백엔드와 프론트엔드 인증 스캐폴딩을 함께 제공합니다.

React와 Inertia 조합에서 Precognition을 사용하기 전에, 먼저 React에서 Precognition 사용하기 섹션을 읽어보세요. Inertia와 함께 사용할 때는 전용 패키지를 설치합니다:

npm install laravel-precognition-react-inertia

설치 후 useForm 함수는 유효성 검사 기능이 추가된 Inertia 폼 헬퍼를 반환합니다.

Inertia 버전의 submit 메서드는 HTTP 메서드와 URL 없이 Inertia의 visit 옵션만 인자로 전달받으며, Promise를 반환하지 않습니다. 이벤트 콜백은 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 기반의 Blade 템플릿에서도 실시간 유효성 검사를 제공할 수 있습니다. 신규 사용자 생성 폼을 예시로 살펴보겠습니다.

먼저, 라우트에 HandlePrecognitiveRequests 미들웨어를 추가하고 폼 리퀘스트를 생성합니다:

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

다음으로 NPM을 통해 Alpine용 Precognition 헬퍼를 설치합니다:

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();

패키지 등록 후, Alpine의 $form 매직을 사용해 폼 객체를 생성합니다. 각 입력 필드에 폼 데이터를 바인딩하고, 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>

사용자가 폼을 작성하면, Precognition은 폼 리퀘스트의 유효성 검사 규칙을 기반으로 실시간 검사 결과를 제공합니다. 디바운스 지연 시간은 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

폼 입력 필드는 값이 변경되고 유효성 검사 응답이 수신된 이후에만 유효/무효 상태로 표시됩니다.

단계별 마법사 폼처럼 사용자가 아직 상호작용하지 않은 필드를 일괄 검사해야 할 때는 validate 메서드에 only 옵션을 전달합니다:

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

제출 진행 중 여부는 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 요청 Promise를 반환합니다:

<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)" 비밀번호인지 검사하는 규칙은 최종 폼 제출 시에만 적용하고, 실시간 검사 시에는 필수 입력 여부와 최소 길이만 검사하고 싶을 수 있습니다. isPrecognitive 메서드로 이를 구현할 수 있습니다:

<?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은 사전 인식 요청 시 파일을 업로드하거나 유효성 검사하지 않습니다. 이는 대용량 파일이 불필요하게 반복 업로드되는 것을 방지하기 위함입니다.

이러한 동작 때문에, 파일 필드는 전체 폼 제출 시

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

번역일: 2026년 6월 25일