개요
Eloquent 모델은 인스턴스화될 때마다 “부팅 처리(boot)“와 “초기화 처리(initialize)“를 실행합니다. 트레이트에 이러한 메서드를 정의해 두면, 모델이 해당 트레이트를use 하는 것만으로 자동으로 호출됩니다.
이 메커니즘을 활용하면 모델에 기능을 주입하는 트레이트를 깔끔하게 구현할 수 있습니다. Laravel 프레임워크 자체도 SoftDeletes 등 많은 트레이트에서 이 패턴을 활용하고 있습니다.
boot와 initialize의 차이
네이밍 규약
bootXxx()
트레이트 이름 앞에boot 접두어를 붙인 static 메서드를 정의하면, 모델 부팅 시 한 번만 호출됩니다.
initializeXxx()
트레이트 이름 앞에initialize 접두어를 붙인 인스턴스 메서드를 정의하면, 모델을 new 할 때마다 호출됩니다.
$casts 에 동적으로 추가할 때에도 사용할 수 있습니다:
PHP Attribute를 통한 명시적 지정
Laravel 12부터는 네이밍 규약에 의존하지 않고 PHP Attribute로 메서드를 명시적으로 지정할 수 있습니다.PHP Attribute를 사용하면 메서드 이름이 트레이트 이름에 얽매이지 않기 때문에, 의미 있는 이름을 붙일 수 있습니다. 여러 개의
#[Boot] 메서드나 #[Initialize] 메서드를 같은 트레이트 안에 정의하는 것도 가능합니다.실전 예제: 패키지 개발에서의 활용
글로벌 스코프의 자동 추가
기본 캐스트 추가
Eloquent 이벤트로 자동 처리
Laravel 프레임워크 내의 예시
Laravel 프레임워크 자체도 많은 트레이트에서 이 패턴을 채택하고 있습니다.
이들을 참고 구현으로 읽어 보면, 패턴에 대한 이해가 더 깊어집니다.
주의 사항
모델 캐시 초기화
boot* 는 클래스마다 한 번만 실행되기 때문에, 테스트 환경에서는 주의가 필요합니다. Model::clearBootedModels() 로 부팅된 캐시를 리셋할 수 있습니다.
실행 순서
같은 모델에 여러 트레이트가use 되어 있을 경우, bootXxx() / initializeXxx() 는 PHP의 트레이트 해결 순서(선언 순서)로 호출됩니다. 의존 관계가 있다면 use 순서에 주의하시기 바랍니다.
정리
트레이트에
bootXxx() / initializeXxx() 를 구현해 두면, 모델에 기능을 주입하는 일이 use 한 줄로 끝나게 됩니다. 패키지에서 모델에 기능을 추가할 때의 정석 패턴입니다.