PHP PHP에서 커스텀 DI 컨테이너 만들기
페이지 정보

영삼이
본문
✅ PHP에서 커스텀 DI 컨테이너 만들기
대형 프레임워크(Laravel, Symfony 등)는 강력한 DI 컨테이너(Dependency Injection Container)를 제공합니다. 하지만 작거나 독립적인 프로젝트에서는 직접 DI 컨테이너를 구현하는 것이 더 가볍고 유연할 수 있습니다. 이 글에서는 PHP로 심플하면서 강력한 DI 컨테이너를 직접 만드는 방법을 다룹니다.
📌 DI 컨테이너 핵심 기능
-
클래스 인스턴스를 자동 생성
-
의존성(생성자 인자)을 자동 주입
-
싱글톤 관리 가능
-
인터페이스 → 구현체 바인딩 가능
🧱 컨테이너 기본 구현
[code=php]
class Container {
private array $bindings = [];
private array $instances = [];
public function bind(string $abstract, string|callable $concrete, bool $singleton = false): void {
$this->bindings[$abstract] = [
'concrete' => $concrete,
'singleton' => $singleton
];
}
public function make(string $abstract): object {
// 이미 싱글톤 인스턴스가 있다면 반환
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
$concrete = $this->bindings[$abstract]['concrete'] ?? $abstract;
if (is_callable($concrete)) {
$object = $concrete($this);
} else {
$object = $this->build($concrete);
}
if (($this->bindings[$abstract]['singleton'] ?? false) === true) {
$this->instances[$abstract] = $object;
}
return $object;
}
private function build(string $class): object {
$ref = new ReflectionClass($class);
$constructor = $ref->getConstructor();
if (!$constructor) {
return new $class;
}
$params = $constructor->getParameters();
$deps = [];
foreach ($params as $param) {
$type = $param->getType()?->getName();
if ($type === null) {
throw new Exception("타입 힌트 없는 의존성: {$param->getName()}");
}
$deps[] = $this->make($type);
}
return $ref->newInstanceArgs($deps);
}
}
[/code]
🧪 사용 예시
[code=php]
interface LoggerInterface {
public function log(string $msg): void;
}
class FileLogger implements LoggerInterface {
public function log(string $msg): void {
file_put_contents('log.txt', $msg . PHP_EOL, FILE_APPEND);
}
}
class UserService {
public function __construct(private LoggerInterface $logger) {}
public function run() {
$this->logger->log("UserService 실행됨");
}
}
$container = new Container();
$container->bind(LoggerInterface::class, FileLogger::class);
$container->bind(UserService::class, UserService::class);
$service = $container->make(UserService::class);
$service->run();
[/code]
🧠 고급 기능 추가 팁
-
컨트롤러 자동 주입 →
Router
와 연동 -
환경별 바인딩 → 개발/운영 Logger 분기
-
태그 시스템 → 여러 서비스 일괄 호출
✅ 요약
-
DI 컨테이너는 클래스 간 결합을 줄이고, 테스트 가능성과 확장성을 높이는 핵심 도구
-
PHP로도 심플하고 유연한 컨테이너를 직접 만들 수 있음
-
작은 프로젝트, 마이크로서비스, CLI 앱 등에 특히 유용
- 이전글PHP + Redis로 간단한 Pub/Sub 구현하기 25.03.28
- 다음글Laravel 없이 PSR-15 미들웨어 구현하기 25.03.28
댓글목록
등록된 댓글이 없습니다.