> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Contracts(계약)

> Laravel의 Contracts의 역할, 파사드와의 차이, 타입 힌트에 의한 주입 방법, 커스텀 Contract의 생성 방법을 설명합니다.

## Contract란

Laravel의 "Contracts"는 프레임워크가 제공하는 핵심 서비스를 정의하는 인터페이스 세트입니다. 예를 들어 `Illuminate\Contracts\Queue\Queue` Contract는 잡의 큐잉에 필요한 메서드를 정의하고, `Illuminate\Contracts\Mail\Mailer` Contract는 메일 전송에 필요한 메서드를 정의하고 있습니다.

각 Contract에는 프레임워크가 제공하는 대응하는 구현이 있습니다. 예를 들어 Laravel은 다양한 드라이버의 큐 구현과 [Symfony Mailer](https://symfony.com/doc/current/mailer.html)를 사용한 메일러 구현을 제공하고 있습니다.

모든 Laravel Contracts는 [전용 GitHub 리포지토리](https://github.com/illuminate/contracts)에 있습니다. 이는 모든 이용 가능한 Contract에 대한 빠른 참조를 제공하며, Laravel 서비스와 연동하는 패키지를 구축할 때 이용할 수 있는 단일의 분리된 패키지입니다.

<Info>
  Contract는 단순한 인터페이스입니다. PHP의 인터페이스와 정확히 같은 구조로 동작합니다. Laravel은 이 인터페이스에 대한 구현을 제공하고, 서비스 컨테이너를 통해 주입합니다.
</Info>

## Contract와 Facade의 차이

[파사드](/ko/facades)와 헬퍼 함수는 서비스 컨테이너에서 Contract를 타입 힌트로 해결할 필요 없이 Laravel의 서비스를 간단하게 이용하는 방법을 제공합니다. 대부분의 경우, 각 파사드에는 대응하는 Contract가 있습니다.

파사드와 Contract의 주요 차이는 다음과 같습니다.

| 관점     | 파사드                    | Contract             |
| ------ | ---------------------- | -------------------- |
| 의존 선언  | 불필요(어디서든 호출 가능)        | 생성자에서 명시적으로 선언       |
| 테스트    | `shouldReceive()`로 모의화 | 표준적인 모의 객체 라이브러리로 교체 |
| 주요 용도  | 애플리케이션 내에서의 손쉬운 사용     | 패키지 개발, 명시적 의존 관리    |
| 코드 가독성 | 임포트가 한 줄로 끝남           | 생성자에서 의존이 한눈에 명확     |

<Tip>
  파사드는 클래스의 생성자에서 요구할 필요가 없지만, Contract는 클래스의 생성자에서 명시적인 의존으로 정의할 수 있습니다. 일부 개발자는 이 명시적인 의존의 정의를 선호하여 Contract를 사용합니다. 다른 개발자는 파사드의 편리함을 선호합니다. **일반적으로 대부분의 애플리케이션은 개발 중에 파사드를 문제없이 사용할 수 있습니다.**
</Tip>

## Contract를 언제 사용할 것인가

Contract와 Facade 중 어느 쪽을 사용할지는 개인의 취향이나 개발 팀의 취향에 달려 있습니다. Contract와 Facade는 어느 쪽이든 견고하고 테스트하기 쉬운 Laravel 애플리케이션을 만들기 위해 사용할 수 있습니다. Contract와 Facade는 서로 배타적이지 않습니다. 애플리케이션의 일부에서는 Facade를 사용하고, 다른 부분에서는 Contract에 의존하는 것도 가능합니다.

특히 Contract가 유용한 상황은 다음과 같습니다.

* **여러 PHP 프레임워크와 연동하는 패키지를 구축하는 경우** — `illuminate/contracts` 패키지를 사용해 Laravel 서비스와의 연동을 정의함으로써, `composer.json`에 Laravel의 구체적인 구현을 요구하지 않아도 됩니다.
* **의존을 명시적으로 하고 싶은 경우** — 생성자만 봐도 클래스가 무엇에 의존하고 있는지 한눈에 알 수 있습니다.
* **구현을 교체하고 싶은 경우** — 서비스 컨테이너를 통해 다른 구현으로 교체하는 것이 용이해집니다.

## Contract 사용법

Contract 구현을 획득하려면 어떻게 해야 할까요? 사실 매우 간단합니다.

컨트롤러, 이벤트 리스너, 미들웨어, 큐 잡, 라우트 클로저 등 Laravel의 많은 종류의 클래스는 서비스 컨테이너를 통해 해결됩니다. 따라서 Contract 구현을 획득하려면 해결되고 있는 클래스의 생성자에서 인터페이스를 "타입 힌트"하기만 하면 됩니다.

```mermaid theme={null}
flowchart LR
    A["서비스 프로바이더<br>bind(Interface, Impl)"] --> B["서비스 컨테이너<br>바인딩 등록"]
    C["생성자<br>타입 힌트: Interface"] --> B
    B --> D["자동 주입<br>Interface의 구현을 해결"]
    D --> E["구체 클래스의 인스턴스<br>교체 자유"]
```

예를 들어 다음 이벤트 리스너를 봐 주세요.

```php theme={null}
<?php

namespace App\Listeners;

use App\Events\OrderWasPlaced;
use App\Models\User;
use Illuminate\Contracts\Redis\Factory;

class CacheOrderInformation
{
    /**
     * 이벤트 리스너를 생성한다
     */
    public function __construct(
        protected Factory $redis,
    ) {}

    /**
     * 이벤트를 처리한다
     */
    public function handle(OrderWasPlaced $event): void
    {
        // ...
    }
}
```

이벤트 리스너가 해결되면 서비스 컨테이너는 클래스의 생성자의 타입 힌트를 읽어 들여 적절한 값을 주입합니다.

## 커스텀 Contract 생성

독자적인 Contract를 만들어 애플리케이션의 컴포넌트 간 의존을 명확히 할 수 있습니다.

<Steps>
  <Step title="인터페이스를 정의한다">
    `app/Contracts` 디렉터리에 인터페이스를 생성합니다.

    ```php theme={null}
    <?php

    namespace App\Contracts;

    interface PaymentGateway
    {
        /**
         * 지정된 금액을 결제한다
         */
        public function charge(int $amount, string $token): bool;

        /**
         * 결제를 환불한다
         */
        public function refund(string $transactionId): bool;
    }
    ```
  </Step>

  <Step title="구현 클래스를 생성한다">
    Contract를 구현하는 클래스를 생성합니다.

    ```php theme={null}
    <?php

    namespace App\Services;

    use App\Contracts\PaymentGateway;

    class StripePaymentGateway implements PaymentGateway
    {
        public function charge(int $amount, string $token): bool
        {
            // Stripe API를 사용한 결제 처리...
            return true;
        }

        public function refund(string $transactionId): bool
        {
            // Stripe API를 사용한 환불 처리...
            return true;
        }
    }
    ```
  </Step>

  <Step title="서비스 프로바이더에서 바인딩한다">
    [서비스 프로바이더](/ko/service-providers)에서 Contract와 구현을 바인딩합니다.

    ```php theme={null}
    use App\Contracts\PaymentGateway;
    use App\Services\StripePaymentGateway;

    $this->app->singleton(PaymentGateway::class, StripePaymentGateway::class);
    ```
  </Step>

  <Step title="타입 힌트로 주입을 받는다">
    컨트롤러나 다른 클래스의 생성자에서 타입 힌트합니다.

    ```php theme={null}
    <?php

    namespace App\Http\Controllers;

    use App\Contracts\PaymentGateway;
    use Illuminate\Http\Request;

    class OrderController extends Controller
    {
        public function __construct(
            protected PaymentGateway $payment,
        ) {}

        public function store(Request $request)
        {
            $this->payment->charge(
                $request->amount,
                $request->payment_token
            );

            // ...
        }
    }
    ```
  </Step>
</Steps>

이 패턴을 통해 결제 서비스를 `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`                |

모든 Contract의 목록은 [illuminate/contracts](https://github.com/illuminate/contracts) 리포지토리에서 확인할 수 있습니다.

## 다음 단계

<Card title="파사드" icon="layer-group" href="/ko/facades">
  파사드의 구조와 테스트 방법을 확인합니다.
</Card>


## Related topics

- [파사드](/ko/facades.md)
- [Collection Deep Dive](/ko/advanced/collection-deep-dive.md)
- [2026년 4월 Laravel 업데이트](/ko/blog/changelog/202604.md)
- [Support Contracts (Arrayable / Jsonable / Htmlable / Responsable)](/ko/advanced/support-contracts.md)
- [AI SDK의 커스텀 프로바이더 만들기](/ko/advanced/ai-sdk-custom-provider.md)
