서비스 컨테이너란
Laravel의 서비스 컨테이너는 클래스의 의존 관계를 관리하고 의존성 주입을 수행하기 위한 구조입니다. 의존성 주입이란 클래스가 필요로 하는 의존을 생성자나 경우에 따라서는 세터 메서드를 통해 클래스로 “주입”하는 것을 말합니다. 다음 예시를 봅시다.PodcastController는 Apple Music 같은 데이터 소스에서 Podcast를 가져와야 합니다. 그래서 Podcast를 가져올 수 있는 서비스를 주입합니다. 서비스를 주입함으로써 테스트 시에 AppleMusic 서비스의 모의 객체(더미 구현)를 간단하게 교체할 수 있습니다.
서비스 컨테이너를 깊이 이해하는 것은 대규모 Laravel 애플리케이션을 구축할 때 필수적입니다. Laravel 코어 자체에 기여하는 데도 도움이 됩니다.
제로 컨피규레이션 해결
클래스가 다른 구체 클래스(인터페이스가 아닌)에만 의존하고 있는 경우, 컨테이너에 그 해결 방법을 알려 줄 필요는 없습니다. 예를 들어 다음 코드를routes/web.php에 작성했다고 합시다.
이 예시는 라우트 파일 내에서 클래스를 정의하고 있지만, 이는 데모용입니다. 실제 애플리케이션에서는 서비스 클래스는
app/Services 디렉터리에 정의해 주세요.Service 클래스를 해결해 라우트 핸들러로 주입합니다. 설정 파일을 준비하지 않고도 의존성 주입의 혜택을 누릴 수 있습니다.
컨트롤러, 이벤트 리스너, 미들웨어 등 Laravel 애플리케이션에서 작성하는 클래스의 대부분은 컨테이너를 통해 자동으로 의존이 주입됩니다.
바인딩
기본 바인딩
대부분의 바인딩은 서비스 프로바이더 안에서 등록합니다. 서비스 프로바이더 안에서는$this->app 프로퍼티를 통해 컨테이너에 접근할 수 있습니다.
bind
bind 메서드를 사용해 클래스나 인터페이스명과 클로저를 전달하여 바인딩을 등록합니다.
App 파사드를 사용합니다.
인터페이스에 의존하지 않는 클래스는 컨테이너에 바인딩할 필요가 없습니다. 컨테이너는 리플렉션을 사용해 이 객체들을 자동으로 해결할 수 있습니다.
singleton
singleton 메서드는 클래스나 인터페이스를 한 번만 해결하도록 바인딩합니다. 한 번 해결된 싱글턴은 이후의 컨테이너 호출에서 같은 인스턴스가 반환됩니다.
instance
기존의 객체 인스턴스를instance 메서드로 컨테이너에 바인딩할 수도 있습니다. 이후 컨테이너 호출에서는 항상 그 인스턴스가 반환됩니다.
인터페이스를 구현에 바인딩하기
서비스 컨테이너의 강력한 기능 중 하나는 인터페이스를 특정 구현에 바인딩할 수 있다는 것입니다. 예를 들어EventPusher 인터페이스와 RedisEventPusher 구현이 있다고 합시다.
EventPusher 구현이 필요한 클래스에 RedisEventPusher를 주입하게 됩니다. 나머지는 생성자에서 EventPusher 인터페이스를 타입 힌트하기만 하면 됩니다.
자동 해결(타입 힌트에 의한 DI)
서비스 컨테이너는 컨트롤러, 이벤트 리스너, 미들웨어 같은 클래스를 해결할 때 생성자의 타입 힌트를 보고 의존을 자동으로 주입합니다.UserRepository가 인터페이스에 의존하지 않는다면 컨테이너로의 등록은 불필요합니다. 다음 라우트에 접근하는 것만으로 컨테이너가 자동으로 의존을 해결해 컨트롤러에 주입합니다.
컨테이너에서의 해결
make 메서드
make 메서드를 사용해 컨테이너에서 클래스 인스턴스를 해결할 수 있습니다.
makeWith 메서드를 사용해 추가 인수를 전달할 수도 있습니다.
자동 주입
실제로는make 메서드를 직접 호출하는 경우가 거의 없습니다. 컨테이너가 해결하는 클래스(컨트롤러, 이벤트 리스너, 미들웨어 등)의 생성자에 타입 힌트를 추가하기만 하면 컨테이너가 자동으로 주입해 줍니다.
파사드와 컨테이너의 관계
Laravel의 파사드는 컨테이너 내의 객체로의 정적 인터페이스를 제공합니다. 예를 들어Cache::get()은 내부적으로 컨테이너에서 Cache 서비스를 가져와 호출하고 있습니다.
생성자 주입의 실전 예시
실제 애플리케이션에서의 전형적인 패턴을 봅시다.1
인터페이스를 정의한다
2
구현 클래스를 생성한다
3
서비스 프로바이더에서 바인딩한다
4
컨트롤러에서 주입을 받는다
Stripe에서 다른 프로바이더로 전환하는 경우에도 바인딩을 한 곳만 변경하면 대응할 수 있습니다.
다음 단계
서비스 프로바이더
서비스 프로바이더를 사용해 바인딩을 등록하는 방법을 배웁니다.