Modern PHP Without a Framework

간만에 모던PHP 모임에서 발표한 자료.

https://github.com/ModernPUG/meetup/tree/master/2018_06

발표 코드와 큰 흐름은 Kevin Smith의 Modern PHP Without a Framework이라는 글에서 가져왔고, 여기에 이런 저런 설명을 붙여서 발표했다.

발표 자료 만드는 도중에 엄청난 고민에 빠졌는데, 문제는 DI(Dependency Injection, 의존성 주입)였다.

DI container를 설명하면서 (내가 만들지 않은) 아래 코드를 예로 들게 되었는데,

class AwesomeClass
{
private $dbConnection;

public function __construct(\PDO $dbConnection)
{
$this->dbConnection = $dbConnection;
}

public function doSomethingAwesome()
{
// Make magic happen with $this->dbConnection
}
}

이 코드는 DI인가, 아닌가?

이 코드는 의존성이 주입되지 않았다. 의존하는 객체를 생성자를 받은 것 뿐이다. 이미 이 ‘대단한’ 클래스는 PDO에 강하게 의존하고 있다.

그럼 DI란? 간단히 설명하면, 의존 관계(토비님은 이 표현이 적당하다고 생각하시는 듯)를 런타임에 맺어주는 것.

그래서 의존성 주입의 적당한 예로 아래처럼 다른 코드로 바꿀까 고민을 많이 했었다.

class PizzaDelivery
{
private $pizza;

public function __construct(PizzaInterface $pizza)
{
$this->pizza = $pizza;
}

public function deliver()
{
// vroong!
}
}

런타임에 HawaiianPizza 인스턴스가 들어온다고 가정을 해보자.

‘의존성을 제거한다’라는 말을 들으면, 예전에는 ‘어차피 이런 코드도 PizzaInterface에 의존을 하고 있구만. 의존성을 제거할 순 없지’이라만 생각을 했는데, 여기저기 찾아보니 의존성 주입에서의 ‘의존성(Dependency)’은 특정 상황을 나타내는 고유명사로 생각하는 게 속이 편하겠다는 생각이 들었다.(이건 논란의 여지를 피해 또 논란 거리를 만드는 건가?)

PizzaDelivery는 HawaiianPizza와의 의존성이 없다. HawaiianPizza와 의존 관계가 만들어지는 건 런타임이다. 그래서 이 코드는 의존성이 주입되는 예시가 된다.

발표에서 PHP-DI라는 DI container라고 스스로 이야기하는 툴을 DI로도 쓰고, Service Locator로도 쓰기도 하는 것에 어째 이물감이 생겼다. 남들을 더 혼란스럼게 하나 싶기도 하고.

생성자에 뭔가를 넘기는 것을 의존성 주입이라고 퉁치는 경우가 많기 때문에, 이것도 REST처럼 정확히 따지고 들자면 꼰대가 되는 것 같지만, 한번쯤 DI의 의미를 깊이 생각해볼 필요가 있을 것 같다.

여기까지가 DI에 대해 공부했던 내용이고, 그 출처는 아래 링크에서 많은 도움을 받았다.

(공부는진행중…)

도움받은 글

http://jwchung.github.io/DI는-IoC를-사용하지-않아도-된다

  • Martin Folwer의 Inversion of Control Containers and the Dependency Injection pattern(박성철님의 번역본 참고), Mark Seemann의 주장(haruair님의 번역본 참고)등을 예로 든 DI에 관한 글이 있었는데, 이 글과 댓글을 읽고 많은 생각을 하게 됐다.

https://justhackem.wordpress.com/2016/05/13/dependency-inversion-terms/

  • 그 댓글에서 논쟁을 벌였던 이규원님의 글 ‘의존성 역전 원리(Dependency Inversion Principle) 관련 용어’

http://toby.epril.com/?p=808

  • 토비님의 DI에서 dependency를 어떻게 번역할 것인가에 대한 글