개발 지식

개발 지식

PHP PHP에서 의존성 주입 제대로 활용하는 법

페이지 정보

profile_image
영삼이
0건 209회 25-03-28 22:46

본문

✅ PHP에서 의존성 주입 제대로 활용하는 법

의존성 주입(Dependency Injection, DI) 은 객체 간의 결합도를 낮추고 테스트 가능성과 확장성을 높이는 중요한 설계 기법입니다.
이 글에서는 PHP에서 DI를 어떻게 활용할 수 있는지 예제를 통해 소개합니다.


💡 의존성 주입이란?

기존 방식은 클래스가 직접 필요한 객체를 생성하거나 가져와서 사용합니다.

[code=php]
class UserService {
    private $db;

    public function __construct() {
        $this->db = new DatabaseConnection(); // 강한 결합
    }
}
[/code]

위 방식은 UserServiceDatabaseConnection에 강하게 결합되어 있어 테스트나 확장이 어렵습니다.
이를 해결하는 방식이 바로 "의존성 주입"입니다.


🔧 생성자 주입 (Constructor Injection)

가장 일반적인 DI 방식은 생성자를 통한 주입입니다.

[code=php]
class UserService {
    private $db;

    public function __construct(DatabaseConnection $db) {
        $this->db = $db;
    }
}
[/code]

이제 UserService는 외부에서 DatabaseConnection을 주입받기 때문에 테스트용 DB 모킹(mocking)도 가능해지고, 다양한 구현체로 대체할 수 있습니다.


🧪 인터페이스를 활용한 느슨한 결합

인터페이스를 도입하면 더욱 유연한 설계가 가능합니다.

[code=php]
interface DatabaseInterface {
    public function query(string $sql);
}

class MySQLConnection implements DatabaseInterface {
    public function query(string $sql) {
        // MySQL 처리
    }
}

class UserService {
    private $db;

    public function __construct(DatabaseInterface $db) {
        $this->db = $db;
    }
}
[/code]

이제 UserServiceMySQLConnection 뿐만 아니라 PostgreSQLConnection 등 다른 구현체도 받을 수 있게 됩니다.


🧰 간단한 DI 컨테이너 구현 예시

간단한 DI 컨테이너를 직접 만들어보면 DI 개념이 더 잘 이해됩니다.

[code=php]
class Container {
    private $bindings = [];

    public function bind($abstract, $concrete) {
        $this->bindings[$abstract] = $concrete;
    }

    public function make($abstract) {
        $concrete = $this->bindings[$abstract];

        // Reflection을 활용해 의존성 분석 및 주입
        $reflector = new ReflectionClass($concrete);
        $constructor = $reflector->getConstructor();

        if (!$constructor) {
            return new $concrete;
        }

        $params = $constructor->getParameters();
        $dependencies = [];

        foreach ($params as $param) {
            $dependencies[] = $this->make($param->getType()->getName());
        }

        return $reflector->newInstanceArgs($dependencies);
    }
}
[/code]

사용 예시:

[code=php]
$container = new Container();

$container->bind(DatabaseInterface::class, MySQLConnection::class);
$container->bind(UserService::class, UserService::class);

$userService = $container->make(UserService::class);
[/code]

🧠 마무리 팁

  • PHP에서는 Laravel, Symfony 등의 프레임워크가 강력한 DI 컨테이너를 내장하고 있습니다.

  • 하지만 프레임워크 없이도 DI는 충분히 구현 가능하고, 실무 설계에서도 많은 이점을 줍니다.

  • 클래스 간 결합도를 낮추고 테스트 가능성을 높이려면 꼭 DI를 적극 활용하세요.


댓글목록

등록된 댓글이 없습니다.