PHP PHP로 간단한 의존성 주입 컨테이너 직접 만들어보기
페이지 정보

영삼이
본문
✅ PHP로 간단한 의존성 주입 컨테이너 직접 만들어보기
의존성 주입(Dependency Injection, DI)은 객체 간의 결합도를 줄이고 테스트 가능성을 높이는 핵심 설계 원칙입니다. PHP에서는 Laravel, Symfony 같은 프레임워크가 DI 컨테이너를 기본 제공하지만, 직접 간단한 DI 컨테이너를 만들어보면 구조를 더 잘 이해할 수 있습니다.
🎯 목표
-
클래스 간 의존성을 자동으로 주입
-
인터페이스 바인딩 지원
-
싱글톤 지원
🧱 Step 1: 기본 컨테이너 클래스
[code=php]
class Container {
private array $bindings = [];
private array $instances = [];
public function bind(string $abstract, callable|string $concrete, bool $singleton = false): void {
$this->bindings[$abstract] = compact('concrete', 'singleton');
}
public function make(string $abstract): object {
// 싱글톤 인스턴스 반환
if (isset($this->instances[$abstract])) {
return $this->instances[$abstract];
}
$concrete = $this->bindings[$abstract]['concrete'] ?? $abstract;
$object = is_callable($concrete)
? $concrete($this)
: $this->build($concrete);
if (($this->bindings[$abstract]['singleton'] ?? false) === true) {
$this->instances[$abstract] = $object;
}
return $object;
}
private function build(string $concrete): object {
$reflector = new ReflectionClass($concrete);
if (!$reflector->isInstantiable()) {
throw new Exception("[$concrete]는 인스턴스화할 수 없습니다.");
}
$constructor = $reflector->getConstructor();
if (!$constructor) return new $concrete;
$parameters = $constructor->getParameters();
$dependencies = [];
foreach ($parameters as $param) {
$type = $param->getType();
if (!$type) {
throw new Exception("타입 힌트 누락: {$param->getName()}");
}
$dependencies[] = $this->make($type->getName());
}
return $reflector->newInstanceArgs($dependencies);
}
}
[/code]
🧩 Step 2: 인터페이스 바인딩 예시
[code=php]
interface MailerInterface {
public function send(string $to, string $msg): void;
}
class SmtpMailer implements MailerInterface {
public function send(string $to, string $msg): void {
echo "메일 발송: $to - $msg\n";
}
}
[/code]
🧰 Step 3: 서비스 클래스
[code=php]
class UserService {
public function __construct(private MailerInterface $mailer) {}
public function notifyUser(string $email): void {
$this->mailer->send($email, "안녕하세요!");
}
}
[/code]
🚀 Step 4: DI 컨테이너로 조립
[code=php]
$container = new Container();
$container->bind(MailerInterface::class, SmtpMailer::class);
$container->bind(UserService::class, UserService::class);
$userService = $container->make(UserService::class);
$userService->notifyUser('kim@example.com');
[/code]
✅ 확장 포인트
-
컨트롤러 자동 주입 →
Router
와 연계 -
싱글톤 자동 처리 → config 기반으로 관리
-
이벤트, 미들웨어 주입 등도 통합 가능
-
PSR-11 ContainerInterface 구현 가능
🧠 요약
기능 | 구현됨 |
---|---|
클래스 자동 생성 | ✅ |
생성자 의존성 주입 | ✅ |
인터페이스 바인딩 | ✅ |
싱글톤 지원 | ✅ |
프레임워크 의존 없음 | ✅ |
의존성 주입은 객체 간 연결을 유연하게 만들고, 테스트 가능한 구조의 기반입니다. 직접 만든 DI 컨테이너는 작고 강력한 PHP 애플리케이션의 핵심 무기가 됩니다.
- 이전글PHP에서 인터페이스 분리 원칙(ISP) 실전 적용하기 25.03.28
- 다음글실무에서 PHP 코드 리팩토링 패턴 5가지 25.03.28
댓글목록
등록된 댓글이 없습니다.