계약(Contracts)
번역일: 2026년 6월 20일
계약(Contracts)
소개
Laravel의 "Contracts"는 프레임워크가 제공하는 핵심 서비스들의 인터페이스 모음입니다. 예를 들어, Illuminate\Contracts\Queue\Queue는 Job을 큐에 넣기 위해 필요한 메서드를 정의하고, Illuminate\Contracts\Mail\Mailer는 이메일 전송에 필요한 메서드를 정의합니다.
각 Contract에는 프레임워크가 제공하는 실제 구현체가 대응됩니다. 예를 들어, Laravel은 다양한 드라이버를 지원하는 큐 구현체와 Symfony Mailer 기반의 메일 구현체를 제공합니다.
모든 Laravel Contract는 별도의 GitHub 저장소에서 관리됩니다. 이를 통해 사용 가능한 Contract 전체를 한눈에 파악할 수 있으며, Laravel 서비스와 연동하는 패키지를 개발할 때 느슨하게 결합된 단일 패키지로 활용할 수도 있습니다.
Contracts vs. Facades
Laravel의 Facade와 헬퍼 함수는 서비스 컨테이너에서 Contract를 직접 꺼내거나 타입 힌트를 작성하지 않고도 Laravel 서비스를 편리하게 사용할 수 있게 해줍니다. 대부분의 Facade에는 동등한 Contract가 존재합니다.
Facade는 클래스 생성자에서 따로 의존성을 선언할 필요가 없는 반면, Contract를 사용하면 클래스가 어떤 의존성을 필요로 하는지 명시적으로 드러납니다. 이처럼 의존성을 명확하게 표현하는 방식을 선호하는 개발자는 Contract를 즐겨 사용하고, 편의성을 중시하는 개발자는 Facade를 선호하는 경향이 있습니다. 일반적인 애플리케이션 개발에서는 Facade만으로도 충분합니다.
NOTE
Facade와 Contracts 중 어느 쪽을 선택하든 Laravel 애플리케이션을 견고하게 만들 수 있습니다. 둘은 서로 배타적인 관계가 아니며, 같은 프로젝트 안에서 혼용해도 전혀 문제없습니다.
언제 Contracts를 사용할까
Contracts와 Facade 중 무엇을 선택할지는 개인이나 팀의 취향에 달려 있습니다. 둘 다 견고하고 테스트하기 쉬운 애플리케이션을 만드는 데 충분합니다. 클래스의 역할을 명확하게 유지한다면, 실제 개발에서 두 방식의 차이를 크게 느끼기 어렵습니다.
다만, 여러 PHP 프레임워크와 연동되는 패키지를 개발할 때는 Contracts 사용을 권장합니다. illuminate/contracts 패키지를 사용하면 composer.json에 Laravel의 구체적인 구현체를 의존성으로 추가하지 않아도 Laravel 서비스와의 연동 방식을 정의할 수 있습니다.
Contracts 사용 방법
Contract의 구현체를 얻는 방법은 매우 간단합니다.
Laravel에서 컨트롤러, 이벤트 리스너, 미들웨어, 큐 Job, 라우트 클로저 등 많은 클래스는 서비스 컨테이너를 통해 해석(resolve)됩니다. 따라서 Contract의 구현체를 사용하려면, 해당 클래스의 생성자에 인터페이스를 타입 힌트로 선언하기만 하면 됩니다.
아래 이벤트 리스너 예시를 살펴보겠습니다:
<?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 레퍼런스
아래 표는 모든 Laravel Contract와 그에 대응하는 Facade를 빠르게 확인할 수 있는 레퍼런스입니다: