> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Precognition

> 폼 전송 전에 서버 측 유효성 검증을 실시간으로 실행하는 Laravel의 기능

## Precognition이란

Precognition은 폼 전송 전에 서버 측 유효성 검증을 실행하는 구조입니다.
프런트엔드에서 검증 규칙을 중복 정의하지 않고, Laravel의 규칙을 그대로 사용할 수 있습니다.

일반 요청과 달리 Precognition 요청에서는 라우트의 미들웨어나 폼 리퀘스트의 검증은 실행되지만 컨트롤러 메서드 본체는 실행되지 않습니다.
따라서 입력 중의 실시간 검증에 적합합니다.

## 설치

Laravel 13에서는 백엔드 측의 `laravel/precognition`을 추가로 설치할 필요가 없습니다.
필요한 것은 프런트엔드용 헬퍼 패키지입니다.

* Vue: `laravel-precognition-vue`
* React: `laravel-precognition-react`
* Alpine.js: `laravel-precognition-alpine`

```shell theme={null}
npm install laravel-precognition-vue
```

```shell theme={null}
npm install laravel-precognition-react
```

```shell theme={null}
npm install laravel-precognition-alpine
```

<Info>
  Inertia는 2.3 이후부터 Precognition 지원이 내장되어 있습니다. Inertia 3에서도 그대로 이용할 수 있습니다.
  Inertia 폼을 사용하는 경우, 일반적으로 `laravel-precognition-vue` / `laravel-precognition-react`의 추가 도입은 불필요합니다.
</Info>

## 백엔드 설정

라우트에 `HandlePrecognitiveRequests` 미들웨어를 추가합니다.
유효성 검증 규칙은 폼 리퀘스트에 모으는 것이 실용적입니다.
폼 리퀘스트에 모으면 규칙의 재사용과 책임 분리가 쉬워집니다.

```php theme={null}
use App\Http\Requests\StoreUserRequest;
use Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests;
use Illuminate\Support\Facades\Route;

Route::post('/users', function (StoreUserRequest $request) {
    // 실제 전송 시에만 여기가 실행된다
})->middleware([HandlePrecognitiveRequests::class]);
```

부작용이 있는 커스텀 미들웨어가 있는 경우, Precognition 시에는 건너뛰어 주세요.

```php theme={null}
public function handle(Request $request, Closure $next): mixed
{
    if (! $request->isPrecognitive()) {
        Interaction::incrementFor($request->user());
    }

    return $next($request);
}
```

## 프런트엔드 연동

### Alpine.js(Blade)

```html theme={null}
<form x-data="{
    form: $form('post', '/users', { name: '', email: '' }),
}">
    @csrf
    <input x-model="form.name" @change="form.validate('name')" />
    <template x-if="form.invalid('name')">
        <div x-text="form.errors.name"></div>
    </template>
</form>
```

### Vue(Inertia.js)

```vue theme={null}
<script setup>
import { useForm } from 'laravel-precognition-vue';

const form = useForm('post', '/users', {
    name: '',
    email: '',
});
</script>

<template>
    <input v-model="form.name" @change="form.validate('name')" />
    <div v-if="form.invalid('name')">{{ form.errors.name }}</div>
</template>
```

### React(Inertia.js)

```jsx theme={null}
import { useForm } from 'laravel-precognition-react';

const form = useForm('post', '/users', {
    name: '',
    email: '',
});

<input
    value={form.data.name}
    onChange={(e) => form.setData('name', e.target.value)}
    onBlur={() => form.validate('name')}
/>
```

### Axios를 사용한 바닐라 JS

Precognition 라이브러리는 Axios를 사용합니다.
기존 Axios 인스턴스를 사용하는 경우 `client.use()`로 교체합니다.

```js theme={null}
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);
```

## 유효성 검증 타이밍 제어

입력마다의 검증에는 `validate()`를 사용합니다.

```js theme={null}
form.validate('email');
```

디바운스 시간은 `setValidationTimeout()`으로 조정할 수 있습니다.

```js theme={null}
form.setValidationTimeout(3000);
```

파일도 매번 검증하고 싶은 경우에는 `validateFiles()`를 사용합니다.

```js theme={null}
form.validateFiles();
```

배열 입력은 와일드카드로 검증할 수 있습니다.

```js theme={null}
form.validate('users.*.email');
```

## 폼 헬퍼

`useForm()`은 전송 상태나 에러 상태를 통합적으로 다룰 수 있습니다.

* `validating`: 유효성 검증 요청 중
* `processing`: 전송 중
* `errors`: 에러 목록
* `valid('field')` / `invalid('field')`: 필드의 검증 상태
* `submit()`: 일반 전송

```js theme={null}
const submit = () => form.submit()
    .then(() => form.reset());
```

## 일반 요청과 Precognition 요청의 비교

다음 다이어그램은 일반 요청과 Precognition 요청의 처리 차이를 보여줍니다.

```mermaid theme={null}
sequenceDiagram
    participant User as 사용자
    participant Frontend as 프런트엔드
    participant Server as Laravel 서버

    User->>Frontend: 폼 입력
    Frontend->>Server: Precognition 요청(Precognition: true 헤더)
    Server->>Server: 유효성 검증 실행(컨트롤러 로직 미실행)
    Server-->>Frontend: 유효성 검증 결과
    Frontend-->>User: 실시간 에러 표시
    User->>Frontend: 폼 전송
    Frontend->>Server: 일반 요청
    Server-->>Frontend: 응답
```

## 관련 링크

* [Laravel 공식: Precognition](https://laravel.com/docs/precognition)
* [Laravel 공식: Validation](https://laravel.com/docs/validation)
