서비스 프로바이더는 패키지의 진입점입니다. 뷰, 설정, 마이그레이션, 라우트 등의 리소스를 Laravel에 등록하는 처리를 여기에 집약합니다.서비스 프로바이더는 Illuminate\Support\ServiceProvider를 상속하며, register와 boot의 두 메서드를 가집니다.
<?phpnamespace Acme\Courier;use Illuminate\Support\ServiceProvider;class CourierServiceProvider extends ServiceProvider{ /** * 패키지의 서비스를 등록 */ public function register(): void { // 서비스 컨테이너에 대한 바인딩은 여기서 수행 $this->mergeConfigFrom( __DIR__.'/../config/courier.php', 'courier' ); $this->app->singleton(CourierManager::class, function ($app) { return new CourierManager($app['config']['courier']); }); } /** * 패키지의 서비스를 부트스트랩 */ public function boot(): void { // 리소스 등록은 여기서 수행 $this->loadRoutesFrom(__DIR__.'/../routes/web.php'); $this->loadViewsFrom(__DIR__.'/../resources/views', 'courier'); $this->loadTranslationsFrom(__DIR__.'/../lang', 'courier'); $this->publishesMigrations([ __DIR__.'/../database/migrations' => database_path('migrations'), ]); $this->publishes([ __DIR__.'/../config/courier.php' => config_path('courier.php'), ], 'courier-config'); $this->publishes([ __DIR__.'/../resources/views' => resource_path('views/vendor/courier'), ], 'courier-views'); }}
register 메서드 내부에서 이벤트 리스너, 라우트, 뷰 등을 등록하지 마세요. 아직 로드되지 않은 다른 서비스 프로바이더의 서비스를 잘못 사용할 가능성이 있습니다. 바인딩 이외의 처리는 반드시 boot 메서드에서 수행합니다.
publishes()의 두 번째 인자로 태그를 지정하면, 사용자가 필요한 리소스만 선택해서 공개할 수 있습니다.
public function boot(): void{ $this->publishes([ __DIR__.'/../config/courier.php' => config_path('courier.php'), ], 'courier-config'); $this->publishesMigrations([ __DIR__.'/../database/migrations/' => database_path('migrations'), ], 'courier-migrations');}
# 설정 파일만 공개php artisan vendor:publish --tag=courier-config# 프로바이더가 제공하는 모든 파일을 공개php artisan vendor:publish --provider="Acme\Courier\CourierServiceProvider"
use Illuminate\Support\Facades\Blade;use Acme\Courier\View\Components\AlertComponent;public function boot(): void{ Blade::component('courier-alert', AlertComponent::class);}
컴포넌트 네임스페이스를 사용하여 일괄 등록할 수도 있습니다.
use Illuminate\Support\Facades\Blade;public function boot(): void{ Blade::componentNamespace('Acme\\Courier\\View\\Components', 'courier');}
{{-- 개별 등록의 경우 --}}<x-courier-alert />{{-- 네임스페이스 등록의 경우 --}}<x-courier::alert />
use Acme\Courier\Console\Commands\InstallCommand;use Acme\Courier\Console\Commands\SyncCommand;public function boot(): void{ if ($this->app->runningInConsole()) { $this->commands([ InstallCommand::class, SyncCommand::class, ]); }}
<?phpnamespace Acme\Courier;class CourierManager{ public function __construct( protected array $config, ) {} public function send(string $to, string $message): bool { // 메시지 발송 처리 return true; } public function track(string $id): array { // 추적 정보 조회 처리 return ['status' => 'delivered']; }}
2
파사드 클래스 생성
Illuminate\Support\Facades\Facade를 상속하고, getFacadeAccessor()에서 서비스 컨테이너의 바인딩 키를 반환합니다.
public function register(): void{ $this->app->singleton(\Acme\Courier\CourierManager::class, function ($app) { return new \Acme\Courier\CourierManager($app['config']['courier']); });}
서비스 컨테이너에 대한 바인딩만 수행하는 프로바이더는 DeferrableProvider 인터페이스를 구현하여 지연 로딩을 구현할 수 있습니다. 서비스가 실제로 필요해질 때까지 프로바이더가 로드되지 않으므로 애플리케이션의 성능이 향상됩니다.
<?phpnamespace Acme\Courier;use Illuminate\Contracts\Support\DeferrableProvider;use Illuminate\Support\ServiceProvider;class CourierServiceProvider extends ServiceProvider implements DeferrableProvider{ public function register(): void { $this->app->singleton(CourierManager::class, function ($app) { return new CourierManager($app['config']['courier']); }); } /** * 이 프로바이더가 제공하는 서비스 목록을 반환 * * @return array<int, string> */ public function provides(): array { return [CourierManager::class]; }}
Laravel은 지연 프로바이더가 제공하는 서비스 목록을 컴파일하여 저장합니다. provides()에 나열된 서비스가 해석될 때만 프로바이더가 로드됩니다.
리소스 등록(뷰, 라우트, 이벤트 리스너 등)이 필요한 프로바이더에는 DeferrableProvider를 사용하지 마세요. 지연 로딩될 경우 해당 리소스가 등록되지 않은 상태로 남게 됩니다.