Macroable 트레이트란
Macroable 트레이트는 클래스를 변경하지 않고 나중에 메서드를 동적으로 추가할 수 있는 구조입니다. Laravel 코어 클래스의 다수가 이 트레이트를 사용하고 있어, 코어 코드를 건드리지 않고 기능을 확장할 수 있습니다.
트레이트의 실체는 Illuminate\Support\Traits\Macroable에 있습니다. 내부적으로는 등록된 매크로를 정적 프로퍼티 $macros에 저장하고, __call / __callStatic 매직 메서드를 통해 호출합니다.
Macroable을 사용하는 클래스
Laravel에는 Macroable에 대응하는 클래스가 많이 있습니다.macro() — 메서드 추가하기
macro()의 첫 번째 인수에 메서드명, 두 번째 인수에 클로저를 전달합니다.
$this는 매크로를 호출한 인스턴스에 바인딩됩니다. 이를 통해 클래스의 프로퍼티나 메서드에 직접 접근할 수 있습니다.
mixin() — 여러 메서드를 한 번에 추가하기
많은 매크로를 한꺼번에 등록하고 싶은 경우에는mixin()을 사용합니다. 믹스인 클래스의 public / protected 메서드가 모두 매크로로 등록됩니다.
mixin()의 메서드는 매크로로 등록되는 클로저를 반환해야 합니다. 메서드 자체의 반환값이 매크로의 구현이 됩니다.서비스 프로바이더에의 등록
매크로는 애플리케이션 부팅 시에 등록해야 합니다.AppServiceProvider의 boot() 메서드가 적절한 위치입니다.
실전적인 유스케이스
컬렉션의 확장
컬렉션에의 커스텀 메서드 추가는 가장 일반적인 사용 예입니다.Str 클래스의 확장
Request 클래스의 확장
Blueprint의 확장(마이그레이션)
스키마의 컬럼 정의를 한꺼번에 매크로화하면 일관된 DB 설계를 유지할 수 있습니다.테스트 응답의 확장
테스트 전용 어서션 메서드를 추가할 수 있습니다.hasMacro() — 매크로 존재 확인
flushMacros() — 매크로 리셋
테스트에서 매크로를 리셋하고 싶은 경우에 사용합니다.정적 매크로
매크로는 인스턴스 메서드로서 뿐만 아니라 정적 메서드로서도 동작합니다.__callStatic에 의해 처리됩니다.
Macroable 트레이트를 자체 클래스에서 사용하기
직접 만든 클래스에도Macroable을 넣을 수 있습니다.
내부 구현의 상세
Closure::bindTo()에 의해 인스턴스에 바인딩됩니다. 이를 통해 $this가 매크로 호출자의 오브젝트를 가리키게 됩니다. 클로저 이외(invokable 오브젝트 등)의 경우에는 바인딩되지 않습니다.
다음 단계
Pipeline 패턴
파이프라인 패턴을 사용해 여러 처리 단계를 직렬로 구성하는 방법을 배웁니다.