메인 콘텐츠로 건너뛰기

모델 이벤트란

Eloquent 모델은 라이프사이클의 각 타이밍에 자동적으로 이벤트를 발화합니다. 이러한 이벤트에 훅을 걸음으로써, 모델의 저장·삭제 등의 전후에 처리를 삽입할 수 있습니다. Eloquent가 발화하는 이벤트는 이하와 같습니다.
이벤트발생 타이밍
retrievedDB에서 모델을 취득했을 때
creating신규 모델을 저장하기 직전
created신규 모델을 저장한 직후
updating기존 모델을 갱신하기 직전
updated기존 모델을 갱신한 직후
saving신규 작성·갱신 어느 쪽으로 저장하기 직전
saved신규 작성·갱신 어느 쪽으로 저장한 직후
deleting모델을 삭제하기 직전
deleted모델을 삭제한 직후
trashed소프트 삭제한 직후
forceDeleting물리 삭제하기 직전
forceDeleted물리 삭제한 직후
restoring소프트 삭제를 복원하기 직전
restored소프트 삭제를 복원한 직후
replicatingreplicate()를 호출했을 때
-ing로 끝나는 이벤트는 변경이 DB에 영속화되기 에, -ed로 끝나는 이벤트는 에 발화됩니다.
매스 업데이트나 매스 삭제(User::where(...)->update(...) 등)에서는, saving, saved, updating, updated, deleting, deleted 이벤트는 발화되지 않습니다. 모델이 실제로는 취득되지 않기 때문입니다.

클로저를 사용한 이벤트 리스너

이벤트를 심플하게 다루고 싶은 경우에는, 모델의 booted 메서드 내에서 클로저를 등록할 수 있습니다.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected static function booted(): void
    {
        static::created(function (User $user) {
            // ユーザー作成後に実行される処理
        });

        static::deleting(function (User $user) {
            // ユーザー削除前に実行される処理
        });
    }
}
처리를 큐로 비동기 실행하고 싶은 경우에는 queueable 헬퍼를 사용합니다.
use function Illuminate\Events\queueable;

static::created(queueable(function (User $user) {
    // キューで非同期実行される
}));

$dispatchesEvents 프로퍼티

Laravel의 이벤트 시스템과 연계하고 싶은 경우에는, $dispatchesEvents 프로퍼티로 모델 이벤트를 독자의 이벤트 클래스에 매핑합니다.
<?php

namespace App\Models;

use App\Events\UserDeleted;
use App\Events\UserSaved;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    /**
     * モデルイベントとイベントクラスのマッピング
     *
     * @var array<string, string>
     */
    protected $dispatchesEvents = [
        'saved' => UserSaved::class,
        'deleted' => UserDeleted::class,
    ];
}
매핑한 이벤트 클래스에는, 컨스트럭터에서 모델의 인스턴스를 받습니다.
<?php

namespace App\Events;

use App\Models\User;

class UserSaved
{
    public function __construct(
        public readonly User $user,
    ) {}
}

Observer 클래스의 작성

하나의 모델에 대해 여러 이벤트를 처리하는 경우, 클로저를 나열하기보다 Observer 클래스에 정리하는 편이 깔끔합니다.
1

Artisan 커맨드로 클래스를 생성한다

make:observer 커맨드로 뼈대를 생성합니다. --model 옵션으로 모델을 지정하면, 대응하는 메서드가 자동으로 추가됩니다.
php artisan make:observer UserObserver --model=User
app/Observers/UserObserver.php가 생성됩니다.
2

각 이벤트의 메서드를 구현한다

메서드명이 이벤트명에 대응합니다. 인수에는 모델의 인스턴스가 전달됩니다.
<?php

namespace App\Observers;

use App\Models\User;

class UserObserver
{
    public function created(User $user): void
    {
        // ユーザー作成後の処理
    }

    public function updated(User $user): void
    {
        // ユーザー更新後の処理
    }

    public function deleted(User $user): void
    {
        // ユーザー削除後の処理
    }

    public function restored(User $user): void
    {
        // ソフトデリート復元後の処理
    }

    public function forceDeleted(User $user): void
    {
        // 物理削除後の処理
    }
}
3

Observer를 Model에 등록한다

등록 방법은 2가지 있습니다. Laravel 13에서는 #[ObservedBy] 어트리뷰트를 사용하는 방법이 권장됩니다.방법 1: #[ObservedBy] 어트리뷰트(권장)모델 클래스에 어트리뷰트를 부여하는 것만으로 등록이 완료됩니다. AppServiceProvider의 변경이 불필요합니다.
<?php

namespace App\Models;

use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
use Illuminate\Foundation\Auth\User as Authenticatable;

#[ObservedBy(UserObserver::class)]
class User extends Authenticatable
{
    //
}
여러 Observer를 등록하는 경우에는 어트리뷰트를 반복하거나, 배열로 전달합니다.
#[ObservedBy(UserObserver::class)]
#[ObservedBy(AuditObserver::class)]
class User extends Authenticatable
{
    //
}
방법 2: AppServiceProvider에서 등록한다AppServiceProviderboot 메서드에서 observe를 호출합니다.
<?php

namespace App\Providers;

use App\Models\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        User::observe(UserObserver::class);
    }
}
#[ObservedBy] 어트리뷰트는 Illuminate\Database\Eloquent\Attributes 네임스페이스에 있습니다. PHP 8.0 이후의 네이티브 구문으로, Laravel 13에서 적극적으로 채용되고 있습니다.

데이터베이스 트랜잭션 내에서의 Observer

모델이 트랜잭션 내에서 작성·갱신되는 경우, 트랜잭션의 커밋 후에 Observer를 실행하고 싶을 때가 있습니다. ShouldHandleEventsAfterCommit 인터페이스를 구현하면 그 동작이 됩니다.
<?php

namespace App\Observers;

use App\Models\User;
use Illuminate\Contracts\Events\ShouldHandleEventsAfterCommit;

class UserObserver implements ShouldHandleEventsAfterCommit
{
    public function created(User $user): void
    {
        // トランザクションがコミットされた後に実行される
    }
}
트랜잭션 밖에서 실행된 경우에는, 통상대로 즉시 실행됩니다.

이벤트를 일시적으로 무효화한다

withoutEvents로 특정 처리만 이벤트를 멈춘다

User::withoutEvents()에 전달한 클로저 내에서는, 일체의 모델 이벤트가 발화되지 않습니다.
use App\Models\User;

$user = User::withoutEvents(function () {
    User::findOrFail(1)->delete();

    return User::find(2);
});

saveQuietly로 저장 시의 이벤트를 멈춘다

이벤트를 발화시키지 않고 모델을 저장하고 싶을 때는 saveQuietly를 사용합니다.
$user = User::findOrFail(1);

$user->name = 'Victoria Faith';

$user->saveQuietly();
동일한 메서드가 삭제·복원·레플리케이트에도 준비되어 있습니다.
$user->deleteQuietly();
$user->restoreQuietly();

실전적인 유스케이스

캐시의 자동 클리어

모델이 갱신·삭제되었을 때에 관련된 캐시를 자동으로 클리어합니다.
<?php

namespace App\Observers;

use App\Models\Post;
use Illuminate\Support\Facades\Cache;

class PostObserver
{
    public function saved(Post $post): void
    {
        Cache::forget("post:{$post->id}");
        Cache::forget('posts:latest');
    }

    public function deleted(Post $post): void
    {
        Cache::forget("post:{$post->id}");
        Cache::forget('posts:latest');
    }
}

감사 로그의 기록

모델의 변경 이력을 자동으로 기록합니다. getDirty()로 변경 전후의 값을 취득할 수 있습니다.
<?php

namespace App\Observers;

use App\Models\AuditLog;
use App\Models\User;

class UserObserver
{
    public function updating(User $user): void
    {
        AuditLog::create([
            'model_type' => User::class,
            'model_id'   => $user->id,
            'changes'    => $user->getDirty(),
            'user_id'    => auth()->id(),
        ]);
    }

    public function deleted(User $user): void
    {
        AuditLog::create([
            'model_type' => User::class,
            'model_id'   => $user->id,
            'changes'    => ['deleted' => true],
            'user_id'    => auth()->id(),
        ]);
    }
}
updating 이벤트는 DB에의 저장 에 발화되므로, getDirty()로 변경 예정의 값을 취득할 수 있습니다. updated 이벤트 후에 호출하면 getDirty()는 비어 있게 됩니다.

관련 모델의 자동 갱신

주문이 완료되었을 때에 재고 수를 자동으로 갱신하는 예입니다.
<?php

namespace App\Observers;

use App\Models\Order;

class OrderObserver
{
    public function created(Order $order): void
    {
        foreach ($order->items as $item) {
            $item->product->decrement('stock', $item->quantity);
        }
    }

    public function deleted(Order $order): void
    {
        foreach ($order->items as $item) {
            $item->product->increment('stock', $item->quantity);
        }
    }
}

다음 단계

상급: PHP 어트리뷰트

#[ObservedBy]를 포함한, Laravel 13의 PHP 어트리뷰트를 한꺼번에 배웁니다.
마지막 수정일 2026년 7월 13일