Laravel 서비스 컨테이너의 객체 바인딩 방법 비교
| 방법 | bind() |
singleton() |
scoped() |
instance() |
|---|---|---|---|---|
| 설명 | 해결될 때마다 새 인스턴스를 생성합니다. | 인스턴스를 하나만 생성하고 후속 요청에서 동일한 인스턴스를 반환합니다. | 각 요청/작업 수명 주기 내에서 인스턴스를 하나만 생성하며 요청이 끝나면 지워집니다. | 기존 인스턴스를 컨테이너에 바인딩하고 해결될 때마다 해당 인스턴스를 반환합니다. |
| 장점 | - 모든 요청에 대해 새로운 인스턴스, 상태 공유 문제 없음 - 깨끗한 메모리 사용 - 독립적인 상태가 필요한 로직에 적합 - 각 요청에 대해 고유한 구성을 제공할 수 있음 |
- 인스턴스를 한 번만 생성하여 시스템 리소스 절약 - 상태 일관성 보장 - 구성 및 리소스 공유에 적합 - 높은 동시성 상황에서 성능이 더 좋음 |
- 메모리 사용량과 상태 공유의 균형 - 요청 내에서 상태를 공유하지만 요청 간에는 격리 - Web 요청 시나리오에 적합 |
- 인스턴스 생성 타이밍 완전 제어 - 인스턴스 상태를 미리 구성 가능 - 특정 구성이 필요한 서비스에 적합 |
| 단점 | - 인스턴스를 반복적으로 생성하기 위해 더 많은 시스템 리소스 필요 - 높은 동시성 하에서 성능에 영향을 줄 수 있음 - 상태 공유가 필요한 시나리오에는 부적합 - 매번 새 인스턴스를 생성하므로 성능 문제가 발생할 수 있습니다. |
- 공유 상태로 인해 추적하기 어려운 버그가 발생할 수 있음 - 독립적인 상태가 필요한 시나리오에는 부적합 - 프로그램이 종료될 때까지 메모리 사용 지속 - 테스트 시 상태 초기화에 특별한 주의 필요 - 인스턴스가 상태를 보유하고 있으면 예기치 않은 동작이 발생할 수 있습니다. |
- 장기간 실행되는 작업에서 문제가 발생할 수 있음 - 요청 수명 주기 이해 필요 - CLI 명령에 부적합 |
- 유연성이 떨어짐 - 인스턴스 구성을 동적으로 조정할 수 없음 - 시작 시 메모리를 점유할 수 있음 - 지연 로딩이나 여러 인스턴스가 필요한 경우에는 부적합 |
| 사용 사례 | 단기 사용 서비스 또는 독립적인 상태가 필요한 클래스에 사용됩니다. | 로거 또는 구성 관리자와 같이 전역적으로 공유되는 서비스에 사용됩니다. | 데이터베이스 연결과 같이 요청 내에서 상태를 유지해야 하지만 요청 간에는 유지하지 않으려는 서비스에 사용됩니다. | 공유 구성 객체와 같이 이미 인스턴스가 있고 이를 재사용하려는 경우에 사용됩니다. |
| 예시 | Product 클래스가 있고 다른 제품 데이터가 요청될 때마다 새로운 Product 인스턴스를 생성하려는 경우. |
Logger 클래스가 있고 일관성을 유지하기 위해 모든 로그 쓰기 작업에서 동일한 인스턴스를 사용하려는 경우. |
ShoppingCart 클래스가 있고 동일한 요청 내에서 장바구니 상태를 공유해야 하는 경우. |
DatabaseConfig 클래스가 있고 애플리케이션이 시작될 때 연결 매개변수를 설정해야 하는 경우. |
예시
bind() 사용
$this->app->bind('Product', function () {
return new Product();
});
app('Product')가 호출될 때마다 새로운 Product 인스턴스를 반환합니다.
singleton() 사용
$this->app->singleton('Logger', function () {
return new Logger();
});
app('Logger')가 호출될 때마다 동일한 Logger 인스턴스를 반환합니다.
scoped() 사용
$this->app->scoped(Transistor::class, function (Application $app) {
return new Transistor($app->make(PodcastParser::class));
});
동일한 요청 수명 주기 내에서 동일한 인스턴스를 공유하고, 다른 요청은 새 인스턴스를 생성합니다.
instance() 사용
$service = new Transistor(new PodcastParser);
$this->app->instance(Transistor::class, $service);
기존 인스턴스를 컨테이너에 직접 바인딩합니다.
요약
Laravel은 현재 Web 요청, CLI 명령, Queue 작업, Console 명령 등 다양한 유형의 시나리오에 적용할 수 있습니다.
따라서 어떤 바인딩 방법을 사용할지 선택할 때는 다양한 시나리오에서 서비스의 요구 사항과 상태 또는 구성을 공유해야 하는지 여부를 고려해야 합니다.