Contract란
Laravel의 “Contracts”는 프레임워크가 제공하는 핵심 서비스를 정의하는 인터페이스 세트입니다. 예를 들어Illuminate\Contracts\Queue\Queue Contract는 잡의 큐잉에 필요한 메서드를 정의하고, Illuminate\Contracts\Mail\Mailer Contract는 메일 전송에 필요한 메서드를 정의하고 있습니다.
각 Contract에는 프레임워크가 제공하는 대응하는 구현이 있습니다. 예를 들어 Laravel은 다양한 드라이버의 큐 구현과 Symfony Mailer를 사용한 메일러 구현을 제공하고 있습니다.
모든 Laravel Contracts는 전용 GitHub 리포지토리에 있습니다. 이는 모든 이용 가능한 Contract에 대한 빠른 참조를 제공하며, Laravel 서비스와 연동하는 패키지를 구축할 때 이용할 수 있는 단일의 분리된 패키지입니다.
Contract는 단순한 인터페이스입니다. PHP의 인터페이스와 정확히 같은 구조로 동작합니다. Laravel은 이 인터페이스에 대한 구현을 제공하고, 서비스 컨테이너를 통해 주입합니다.
Contract와 Facade의 차이
파사드와 헬퍼 함수는 서비스 컨테이너에서 Contract를 타입 힌트로 해결할 필요 없이 Laravel의 서비스를 간단하게 이용하는 방법을 제공합니다. 대부분의 경우, 각 파사드에는 대응하는 Contract가 있습니다. 파사드와 Contract의 주요 차이는 다음과 같습니다.| 관점 | 파사드 | Contract |
|---|---|---|
| 의존 선언 | 불필요(어디서든 호출 가능) | 생성자에서 명시적으로 선언 |
| 테스트 | shouldReceive()로 모의화 | 표준적인 모의 객체 라이브러리로 교체 |
| 주요 용도 | 애플리케이션 내에서의 손쉬운 사용 | 패키지 개발, 명시적 의존 관리 |
| 코드 가독성 | 임포트가 한 줄로 끝남 | 생성자에서 의존이 한눈에 명확 |
Contract를 언제 사용할 것인가
Contract와 Facade 중 어느 쪽을 사용할지는 개인의 취향이나 개발 팀의 취향에 달려 있습니다. Contract와 Facade는 어느 쪽이든 견고하고 테스트하기 쉬운 Laravel 애플리케이션을 만들기 위해 사용할 수 있습니다. Contract와 Facade는 서로 배타적이지 않습니다. 애플리케이션의 일부에서는 Facade를 사용하고, 다른 부분에서는 Contract에 의존하는 것도 가능합니다. 특히 Contract가 유용한 상황은 다음과 같습니다.- 여러 PHP 프레임워크와 연동하는 패키지를 구축하는 경우 —
illuminate/contracts패키지를 사용해 Laravel 서비스와의 연동을 정의함으로써,composer.json에 Laravel의 구체적인 구현을 요구하지 않아도 됩니다. - 의존을 명시적으로 하고 싶은 경우 — 생성자만 봐도 클래스가 무엇에 의존하고 있는지 한눈에 알 수 있습니다.
- 구현을 교체하고 싶은 경우 — 서비스 컨테이너를 통해 다른 구현으로 교체하는 것이 용이해집니다.
Contract 사용법
Contract 구현을 획득하려면 어떻게 해야 할까요? 사실 매우 간단합니다. 컨트롤러, 이벤트 리스너, 미들웨어, 큐 잡, 라우트 클로저 등 Laravel의 많은 종류의 클래스는 서비스 컨테이너를 통해 해결됩니다. 따라서 Contract 구현을 획득하려면 해결되고 있는 클래스의 생성자에서 인터페이스를 “타입 힌트”하기만 하면 됩니다. 예를 들어 다음 이벤트 리스너를 봐 주세요.커스텀 Contract 생성
독자적인 Contract를 만들어 애플리케이션의 컴포넌트 간 의존을 명확히 할 수 있습니다.서비스 프로바이더에서 바인딩한다
서비스 프로바이더에서 Contract와 구현을 바인딩합니다.
Stripe에서 다른 프로바이더로 전환하는 경우에도 바인딩을 한 곳만 변경하면 되며, 컨트롤러 코드는 변경할 필요가 없습니다.
주요 Contract 목록
자주 사용하는 Contract와 그 대응하는 파사드의 대응표입니다(일부 발췌).| Contract | 대응하는 파사드 |
|---|---|
Illuminate\Contracts\Auth\Access\Gate | Gate |
Illuminate\Contracts\Auth\Factory | Auth |
Illuminate\Contracts\Bus\Dispatcher | Bus |
Illuminate\Contracts\Cache\Factory | Cache |
Illuminate\Contracts\Cache\Repository | Cache::driver() |
Illuminate\Contracts\Config\Repository | Config |
Illuminate\Contracts\Console\Kernel | Artisan |
Illuminate\Contracts\Container\Container | App |
Illuminate\Contracts\Encryption\Encrypter | Crypt |
Illuminate\Contracts\Events\Dispatcher | Event |
Illuminate\Contracts\Filesystem\Factory | Storage |
Illuminate\Contracts\Filesystem\Filesystem | Storage::disk() |
Illuminate\Contracts\Hashing\Hasher | Hash |
Illuminate\Contracts\Mail\Mailer | Mail |
Illuminate\Contracts\Notifications\Dispatcher | Notification |
Illuminate\Contracts\Queue\Factory | Queue |
Illuminate\Contracts\Queue\Queue | Queue::connection() |
Illuminate\Contracts\Queue\ShouldQueue | — |
Illuminate\Contracts\Redis\Factory | Redis |
Illuminate\Contracts\Routing\ResponseFactory | Response |
Illuminate\Contracts\Routing\UrlGenerator | URL |
Illuminate\Contracts\Session\Session | Session::driver() |
Illuminate\Contracts\Translation\Translator | Lang |
Illuminate\Contracts\Validation\Factory | Validator |
Illuminate\Contracts\View\Factory | View |
다음 단계
파사드
파사드의 구조와 테스트 방법을 확인합니다.