의존성 주입(Dependency Injection, DI)은 하나의 객체가 다른 객체가 필요로 하는 의존성(종속 객체)을 외부에서 대신 공급해 주는 프로그래밍 기법입니다. 이러한 소프트웨어 설계 방식을 적용하면 의존성을 코드 내부에 직접 하드코딩할 필요가 없어지며, 런타임과 컴파일 시점 모두에서 의존성을 유연하게 교체할 수 있습니다.
객체를 주입하는 방법은 여러 가지가 있지만, 그중 가장 널리 알려진 두 가지 방식인 생성자 주입과 세터 주입을 예제와 함께 살펴보겠습니다.
1. 생성자 주입(Constructor Injection)
생성자 주입은 클래스의 생성자(__construct)를 통해 필요한 의존성을 전달받는 방식입니다. 객체가 생성되는 순간 의존성이 함께 주입되기 때문에, 클래스 인스턴스는 항상 필요한 값이 준비된 온전한 상태로 시작할 수 있습니다.
예제
<?php
class Programmer {
private $skills;
public function __construct($skills){
$this->skills = $skills;
}
public function totalSkills(){
return count($this->skills);
}
}
$createskills = array("PHP", "JQUERY", "AJAX");
$p = new Programmer($createskills);
echo $p->totalSkills();
?>
실행 결과
3
2. 세터 주입(Setter Injection)
세터 주입은 세터(setter) 메서드를 호출하여 클래스에 의존성을 주입하는 방식입니다. 생성자 주입과 달리 객체를 먼저 생성한 뒤에도 의존성을 설정하거나 언제든 교체할 수 있다는 점이 특징입니다.
예제
<?php
class Profile {
private $language;
public function setLanguage($language){
$this->language = $language;
}
}
$profile = new Profile();
$language = array("Hindi", "English", "French");
$profile->setLanguage($language);
?>
참고로 위 예제의 배열은 반드시 array(...) 형태로 작성해야 합니다. $변수[...]처럼 대괄호를 함수 호출 형태로 잘못 사용하면 PHP 파싱 오류가 발생하니 주의하세요.
의존성 주입의 장점
- 확장 용이성: 새로운 의존성을 추가할 때 새로운 세터 메서드만 작성하면 되므로, 기존 코드를 수정하거나 손상시킬 염려가 없습니다.
- 낮은 결합도: 클래스 간 결합도가 줄어들어 코드 재사용성이 높아지고 유지보수가 한결 수월해집니다.
- 테스트 편의성: 단위 테스트 시 실제 객체 대신 목(mock) 객체를 손쉽게 주입할 수 있어 테스트 작성이 간편합니다.
- 유연한 구성: 런타임 또는 컴파일 시점에 의존성 구현체를 자유롭게 교체할 수 있습니다.
이처럼 의존성 주입은 코드의 유연성과 테스트 용이성을 동시에 끌어올려 주는 핵심 설계 패턴입니다. 특히 규모가 점점 커지는 PHP 프로젝트에서는 객체 관리가 체계적으로 이루어져 개발 생산성과 코드 품질 향상에 큰 도움이 됩니다.