루비나 파이썬 같은 다이나믹 언어 또는 다이나믹 타입 언어의 특성을 가진 언어에서는 왜 DI가 인기가 없는가, 또는 왜 DI가 사용되지 않는가 하는 질문을 본 적이 있다. 그리고 그 대답으로 그런 언어들을 잘 안다고 하는 사람들이 이런 식의 답을 달았던 것이 생각난다.

DI는 디자인패턴과 마찬가지로 자바와 같은 스태틱 타입 언어의 단점 또는 한계 때문에 필요한 것일 뿐이고, 루비나 파이썬 같은 다이나믹 타입 언어에서는 언어차원에서 DI기능을 손쉽게 해결해주기 때문에 DI가 필요없어서 사용하지 않는다

 

과연 그런가?

짧게 대답하자면 "DI을 알게 된 이후로 들었던 수없이 많은 황당한 이야기의 하나"라고 하겠다.

벌써 10월이 된데다 RC1이 나온 탓에 할 일이 산더미지만, 트위터나 미투도 안하는 주제에 블로그도 잘 안쓰는 요즘의 게으른 삶에 대한 반성으로 좀 더 길게 얘기해보자.

 

DI의 기원과 본질

많은 사람들이 가진 오해는 DI라는 프로그래밍 모델과 DI 프레임워크(또는 컨테이너)의 혼동에서 출발한다고 생각한다. DI는 IoC의 일종으로 생각하면 DI도 당연히 프레임워크를 전제로 하는 개념이라고 생각할 수도 있다. 하지만 IoC가 프레임워크의 동작원리이긴 하지만 프레임워크가 없이도 IoC를 적용할 수 있는 것처럼, DI역시 프레임워크 또는 컨테이너를 사용하므로 그 가치가 더 드러나긴 하지만 기본적으로는 객체지향(어떤 이들의 주장을 따르자면 자바와 같이 꾸진 특정 객체지향) 프로그래밍의 한가지 기법에 불과한 것이다.

DI라는 개념을 유행시키고 널리 알린 것은 누구나 동의할 수 있듯이 스프링이다. 스프링의 등장 이후로 DI는 매우 빠르게 인정받고 확산되어서 적어도 자바에서는 DI는 누구나 알아야 할 표준 프로그래밍 모델이자 패턴이되었다. 스프링이 DI를 바탕에 깔긴 했지만 종합적인 애플리케이션 프레임워크를 지향하고 덩치가 커져가는 것에 반해서, 구글주스와 같은 최신 자바의 언어적 장점을 잘 살려서 DI에 최적화된 기능을 제공하는 것도 등장했다. 구글내부에서는 일반적인 JEE 모델은 아니지만 수백만 라인이상되는 복잡한 서비스 또는 내부 애플리케이션 개발에 이 구글주스를 활용하고 있다고 한다. 씸은 나름대로 In/Out 개념으로 확장해서 DI를 bijection이라는 용어를 만들어서 적용하기도 했으며, 스프링과 주스에 발목잡히긴 했지만 표준 DI 스펙으로 만들어 제출하기도 했다. 또 자체 DI 기능을 제공하는 제품이나 오픈소스 프로젝트들도 적지 않다. Maven이 사용하는 DI프레임워크인 Plexus도 그 동네에서는 제법 유명한가보다.

 

스프링을 DI의 기원으로 보자면, 스프링의 코드가 만들어진 동기이자 배경인 로드 존슨의 One-on-One J2EE Design & Development라는 책을 살펴봐야 한다. 그 책에서 내가 가장 흥미롭게 생각하는 것은 4장인가에 나오는 개첵지향 디자인 테크닉에 관한 부분이었다. 로드 존슨이 한 유명한 얘기인 "J2EE보다는 자바가 더 중요하고, 자바 보다는 객체지향이 더 중요하다"라는 말을 생각해보면 그가 객체지향설계와 프로그래밍 기술에 얼마나 중요한 가치를 두었는지 이해할 수 있을 것이다. 내가 처음 그가 쓴 OO디자인 테크닉에 관한 내용을 읽어보니 이건 마치 GoF의 Design Pattern의 축소판을 보는 듯 했다. GoF의 DP책의 서론인 1장과 오브젝트 합성(object composition)을 통한 확장기법을 다룬 Object scope를 가지는 주요 패턴에 관한 이야기를 압축에서 정리한 것이다. programming to interface나 favour composition over inheritance와 같은 GoF DP의 1장에 나온 패턴에 적용된 핵심 원리도 그렇고, 프레임워크의 동작원리인 IoC에 대한 설명도 마찬가지이다.  나중에 비교해보니 어떤 문장은 GoF책의 내용을 단어 하나 바꾸지 않고 그대로 옮긴 것도 있고 표현은 조금 바꿨으나 내용은 그대로 가져다 쓴 것도 적지 않게 발견된다.

스프링은 자바 엔터프라이즈 개발에서 POJO(스프링 쪽 용어로는 simple objects) 프로그래밍을 제대로 적용할 수 있도록 돕는 것이 그 핵심철학이자 목표이라고 2006년 SpringOne에서 소개된 적이 있다. 나도 그 이후로 그 철학과 목표를 자주 언급하곤 하는데, POJO가 목표다라고만 하면 뭔가 빠진 느낌이다. POJO개발을 하는 이유가 무엇인가? 왜 스프링이 DI를 극단적일 정도로 적용해서 각종 기술적인 문제들과 환경에 종속된 코드가 아닌 순수한 자신의 로직만을 담고 있는 POJO라 불리는 단순한 자바 오브젝트를 만들려고 할까? 단지 코드를 간단하게 하려고? 그건 아니다.

스프링이 결국 추구하는 것은 자바의 언어적인 특성, 즉 객체지향 언어의 장점을 극대화 하고, 객체지향기술이 주는 최고의 장점인 유연성(또는 그 때문에 얻어지는 코드의 수정 없는 재사용성)을 극대화하려는 것이다. 그리고 그 적용기법으로 다양한 객제지향설계 테크닉, 패턴들을 추구한다.  환경과 기술에 종속적이며 침투적인 기술로는 그런 유연성을 얻을 수 없기 때문이다.

 

로드 존슨이 DI를 생각한 이유는 기본적으로 그것이 유연한 객체지향설계의 가장 대표적인 기법이었기 때문이고, DI를 지원하는 프레임워크를 만든 이유는 그 기법을 제대로 적용하기 위해서 그 단점을 극복하려고 했기 때문이다.

 

나는 DI의 기원을 GoF패턴의 전략패턴(strategy pattern)에서 찾는다. 물론 DI는 패턴을 스코프로 분류했을 경우에 object scope에 해당하는 모든 패턴에 다 들어맞는다. 상속을 확장을 위해서 사용하는 class scope구조에는 DI가 적용되지 않는다(DI를 적용하다보니 가끔 필요한 경우가 있긴 하다. method injection은 상속을 통한 확장기법의 특별한 사례이다).

그 중에서 전략패턴이 가장 대표적인 이유는 GoF패턴 책에 DI가 구체적으로 설명되어있기 때문이다.  전략패턴에 관한 내용에 보면 오브젝트의 협력관계에 관한 부분이 있고 거기에 이런 표현이 나온다.

A context forwards requests from its clients to its strategy. Clients usually create and pass a ConcreteStrategy object to the context; thereafter, clients interact with the context exclusively. There is often a family of ConcreteStrategy classes for a client to choose from.

나는 이 내용만큼 DI를 잘 설명해주는 것이 없다고 생각한다.

전략패턴의 구조를 생각하면 보통 다음과 같이 두 오브젝트의 구조로만 생각하기 쉽다.

Context –> Strategy(ConcreteStrategyA, ConcreteStrategyB)

Context가 사용(의존)하는 알고리즘(전략)을 자유롭게 교체해서 사용하기 위해서 이를 오브젝트 합성 구조로 분리하고 Strategy라는 인터페이스를 두고 Context는 이에 대해서만 프로로그래밍 하도록 만든 것이다(programming to interface). 그 덕분에 Strategy를 상속한 구체적인 클래스를 자유롭게 교환하거나, 새롭게 만들어서 이를 Context가 사용하게 만들 수 있다. 여기서 핵심은 구체적인 Strategy를 바꾸더라도 Context는 수정할 필요가 없다는 점이다. 이를 통해서 기능 확장(strategy)에는 열려있고 변경(context)에는 닫혀있는 OCP를 충실히 지키며, 코드의 수정 없이 재사용이 가능한 Context가 만들어지는 것이다. 유연성(확장가능)과 재사용(변경없이)이라는 OO의 장점을 잘 살린 구조를 만들 수가 있다.

여기서 관건은 이 두 오브젝트 사이의 협력구조로만은 사실 이것을 이룰 수 없다는 점이다. 모델링타임시 코드에서는 인터페이스 의존관계를 가진 다는 점은 장점이지만, 실전(런타임시)에서는 구체적인 클래스의 오브젝트와 연결(링크)이 필요하다. 그래서 제3의 존재가 등장하는 것이다.

위의 설명을 보자면 context와 strategy외에 제 3의 존재인 client가 필요함을 설명하고 있다. 사실은 다음과 같은 구조가 되는 것이다.

Client –> Context –> Strategy(ConcreteStrategy…)

Context 스스로 구체적인 strategy클래스 정보를 가지고 있으면 이 모든 패턴과 원칙을 다 깨뜨릴 수 밖에 없다. 따라서 실전에서 구체적인 오브젝트에 대한 정보는 client가 context에게 pass(또는 주입, 삽입, 제공 머라고 해도 좋다)해줘야 한다고 명시하고 있는 것이다. 그 후에는 client는 그 뒤에 어떤 strategy가 있는지 상관없이 client는 context만을 보고 사용하면 그만인 것이다.

이게 바로 DI이다.

DI가 뭐 거창하고 대단한 것이라고 오해하기 쉬운데 가장 원시적이며, 핵심적인 DI란 오브젝트 합성 구조를 통한 확장성을 보장받기 위해서 그 둘(context, strategy) 말고 제3의 존재(클라이언트든 뭐든)가 필요하고 그 제3의 존재가 런타임 의존관계(링크)를 제공해줘야 한다는 뜻이다. 그리고 그 방법과 장점에 대해서는 이미 GoF의 전략패턴에서 잘 설명하고 있다.

 

GoF는 이런 방법의 consequence의 하나로 다음과 같은 문제를 언급하고 있다.

A choice of implementations. Strategies can provide different implementations of the same behavior. The client can choose among strategies with different time and space trade-offs.

Clients must be aware of different Strategies. The pattern has a potential drawback in that a client must understand how Strategies differ before it can select the appropriate one. Clients might be exposed to implementation issues. Therefore you should use the Strategy pattern only when the variation in behavior is relevant to clients.

DI방식으로 전략패턴을 적용하는 것의 단점은 클라이언트에 막중한 짐이 주어진다는 점이다. 또한 구체적인 구현에 노출되어버린다는 점이다.

단지 C->C->S구조가 전부라면 뭐 상관없다. 하지만 client도 역시 context와 전략패턴 또는 오브젝트 합성구조로 연결되어있다면 어쩔 것인가? client자체가 단지 context가 유연한 방식으로 strategy와 연결되게 하고 실행시키는 것 이상의 자신만의 책임을 가진 클래스라면 어쩔 것인가? 그런 경우 클라이언트는 자신의 책임 외에 과중하게 strategy에 대한 정보를 알고 이를 만들고 context에게 주입(전달)하는 등의 이중 책임을 떠맡는 것이다. 따라서 GoF는 클라이언트 관점에서 이를 주의해서 사용하도록 권고하고 있다.

여기까지가 원시적인 DI의 모습이다. 어쨌든 모든 제3의 오브젝트가 다른 두 개의 오브젝트 사이의 유연성을 보장하기 위한 목적으로 한쪽(strategy, dependent object)에 대한 정보(dependency)를 다른 오브젝트(context)에게 전달한다면 이는 모두 DI이다. 이를 통해서 두 가지 핵심 오브젝트 사이에서는 OCP를 충실하게 지키는, 유연하고 재사용성이 높은 구조와 코드가 만들어지는 것이다.

따라서 오브젝트 사이의 관계를 통해서 프로그램이 만들어지는 모든 객체지향언어와 기술에는 DI가 적용가능하며, 실제로 다들 사용하고 있다.

 

GoF패턴 책에는 나타나지 않지만 자바언어의 특징(또는 한계)을 잘 살려서 로드 존슨이 적극 사용한 패턴이 템플릿-콜백 패턴이다. 이 패턴은 전략패턴의 특별한 케이스라고 로드 존슨이 그 빨간 책에서 잘 설명해주고 있다. 자세히 살펴보면 템플릿-콜백 패턴은 이 client-context-strategy라는 전략패턴과 DI의 구조가 선명하게 적용된 케이스이다. 다만 자바에는 전달가능한 메소드(펑셔널 오브젝트, 코드블록, 프로시져 등등 머라고 부르던 간에)라는 개념이 없으므로, 단 하나의 메소드만을 가진 인터페이스를 구현한 오브젝트를 일종의 메소드 오브젝트 개념으로 사용하는 것이다. 이 패턴에서는 클라이언트의 역할이 아주 명확하게 잘 드러난다. 클라이언트는 매번 템플릿(context)가 사용할 코드블록인 콜백(strategy의 구현)을 전달한다. 이를 통해서 템플릿은 전혀 수정하지 않고도 매번 템플릿이 사용하는 주요기능을 바꿔서 사용할 수 있게 된다. 역시 템플릿을 호출하는 클라이언트가 콜백(전략)을 만들고 메소드 파라메터로 주입(DI)하는 방식으로 동작한다. 전략패턴-DI 구조의 특별한 케이스일 뿐이다.

 

DI vs DI 프레임워크

스프링 개발자라면 당연히 알고 있겠지만 스프링의 DI를 담당하는 컨테이너 오브젝트가 구현해야 하는 핵심 인터페이스의 이름은 BeanFactory이다. 사실상 DI프레임워크란 Bean, 즉 오브젝트 팩토리이다. 구지 빈이라는 이름을 붙인 이유는 그것이 컨테이너에 등재되어서 관리되어지는 오브젝트(managed object)이기 때문에 붙인 별명일 뿐이다.

템플릿-콜백과 같은 특별한 케이스를 제외하자면 전략패턴-DI는 GoF가 말한 consequence를 가진다. 즉 클라이언트의 책임이 크고, 너무 구체적인 정보에 노출되어있을 뿐더러, 다중 오브젝트 합성 구조에서는 client를 더 이상 확장할 수 없게 만든다.

따라서 원래 클라이언트가 하던 두개의 오브젝트 사이의 런타임 링크를 만들어주는 DI역할을 전담할 별도의 오브젝트를 두는 것이다. 그것이 마틴 파울러 표현으로 보면 Assembler이고, 내가 좋아하는 용어로 보자면 Object Factory 또는 스프링 표현으로는 BeanFactory인 것이다. 클라이언트의 책임이었던 DI작업을 별도의 팩토리로 빼놓으면 단지 두 계층의 오브젝트 구조가 아니라 이를 더 확장한 복잡하고 많은 의존관계를 가지는 복잡 오브젝트-합성 구조에도 이 개념을 일반화해서 적용가능해진다. 그러기 위해선 매번 오브젝트 팩토리에 DI된 오브젝트를 요청해서 가져오는 것이 아니라, 아예 애플리케이션 전체를 DI로 구성해놓는 것이 훨씬 편하다는 개념을 가지게 된 것이고 이를 편리한 프레임워크로 만든 것이 결국 스프링이었다.

스프링의 특징은 프로그래밍 모델과 설정(configuration) 모델을 구분한 것인데, 프로그래밍 모델은 기본적으로 오브젝트 합성구조를 가지며 생성자,설정자,메소드 심지어 필드 같은 DI 받을 수 있는 메카니즘을 제공하면서 인터페이스 프로그래밍을 적용한 것이고, 설정 모델은 XML, 애노테이션 또는 자바코드 자체를 전략패턴의 클라이언트가 그랬듯이 DI해주는 제3의 존재로 손쉽게 만들 수 있도록 해주는 것이다.

 

정말 다이나믹 (타이핑) 언어는 DI가 필요없을까?

객체 사이의 유연성을 필요로 한다면 모든 객체지향언어는 DI가 가장 좋은 방법이고 다이나믹 타이핑 언어 또한 예외는 아니다. 단지 그 메카니즘 면에서 유연하고, 자동화 면에서는 불편할 뿐이다.

내가 그나마 초큼 아는 다이나믹 타이핑 언어는 루비이니 루비를 가지고 생각해보자.

루비라고 해서 Context가 Strategy를 직접 알고 스스로 만든다면 역시 Strategy에 종속된다. 따라서 생성자를  이용하든 메소드를 이용하든, 제3의 존재가 실제 Context가 사용할 구체적인 객체(그것이 비록 런타임시에 다이나믹하게 바뀌었다고 할지라고 아무튼 사용할 그 놈)와 연결해줘야 한다.

물론 루비는 자바와 달리 타입제한이 없으며 클래스 개념이 매우 유연하다는 장점이 있다. 자바와 같은 매우 엄격한 타입을 체크하는 언어는 인터페이스를 사용해야지만 오브젝트 합성구조가 가능하다. 하지만 루비는 덕 타이핑을 통해서 실제 호출가능한 메소드를 가지고 있기만 하면 언제든지 대체가 가능하다. 심지어 메소드가 없어도 처리할 수 있는 기법도 있다. 따라 루비와 같은 언어는 인터페이스가 필요없다는 것은 맞는 말이다.

또한 아예 클래스 자체를 바꾸거나 변경하는 것도 가능하다. 루비의 클래스는 자바처럼 클래서로더당 한번 읽으면 그만인 읽기전용 정보가 아닌, 유연한 오브젝트이고 클래스 이름은 그 오브젝트에 대한 이름일 뿐이다. 소위 오픈 클래스라고 하는 개념은 기존의 클래스의 구현 내용을 확장하거나 변경할 수 있으며, 인스턴스 단위로도 가능하다. 따라서 목 오브젝트와 같은 각종 테스팅 기법에서 막강한 위력을 발휘한다.

이렇게 다이나믹 타이핑 언어 또는 다이나믹 언어이기 때문에 가지능 장점은 DI의 메카니즘인 인젝션이 훨씬 유연하고 간단한 코드로 가능하다는 것이다. 하지만 그렇다고 DI가 필요없다는 말은 틀렸다. 지금 설명한 그런 모든 작업자체가 DI이다. 테스트 할 때마다 사용할 클래스를 MyObject에서 MyMockObject라고 코드를 뜯어고치지 않을 수 있는 이유는 무엇인가? 바로 이런 저런 방법을 통해서 런타임 의존관계를 제3자가 설정 또는 변경해주기 때문이다. 바로 전략패턴의 클라이언트가 하는 그 역할 그대로이다.

따라서 루비는 코드를 통해서 수동으로 DI하기에 더 할나위 없이 좋은 언어이다. 나도 그런 점이 매우 매력적이라고 생각한다. 하지만 잠깐 코드를 통해서 클래스를 바꿔치기 하거나, 덕 타이핑을 이용해서 유사한 메소드를 정의해서 사용하는 것과 같은 일시적인 DI방법 또는 블록과 같이 코드블록 오브젝트를 전달해서 템플릿성의 코드가 사용하게 하는 기법등에 적용된 DI등만이 전부가 아니다. 스프링과 같이 애플리케이션 전체의 구성자체를, 또는 모든 기술적이거나 프레임워크 의존적인 코드를 개발자 코드에서 제거하는 것과 같은 포괄적인 DI를 위해서라면 별도의 툴이나 프레임워크를 사용하는 것이 필요하다. 몰랐는데 루비에도 DI 프레임워크라고 이름을 달고 나온 것들이 제법 많이 있고, 사용하기도 하는 것 같다. 파이썬용으로 Spring.Python인가 하는 것도 만들어진 것도 있다고 한다.

 

그럼 루비에서는 DI 프레임워크를 왜 많이 사용하지 않을까?

그건 나도 모른다. 사실은 자바에서도 DI 도구없이 이미 10년 이상을 개발해왔고 지금도 역시 그 없이도 잘만 개발하는 곳이 넘처난다. 왜 그럴까? 구지 필요성을 못느껴서일까? 무지해서?

아마도 DI 프레임워크 없이도 코드 레벨에서 DI를 잘 사용했기 때문일 수도 있고, 객체지향언어의 유연성에 그다지 목매지 않아서 일 수도 있다. 의존관계가 바뀌면 그냥 코드를 뜯어고치거나, 애플리케이션 로직과 기술 코드를 짬뽕해서 쓰거나 그래도 그럭저럭 개발하고 사용할 수 있으니까 그럴 것이다. DI의 설정을 만드는 것보다 코드로 필요할 때(아마 테스트?) 적절한 변경만 해서 사용하는게 낫다고 생각하면 그러면 될 것이다.

그런면에서 나는 DI 프레임워크를 꼭 사용해야 한다고 주장하고 싶지는 않다. 자바를 가져다 객체지향언어가 아닌 C처럼 개발하든, 루비를 마치 스태틱 타입언어처럼 사용한들 뭐 어쩌겠는가. 안돌아가는 것도 아니고 말이다. 나야 DI가 편하고, 그게 없으면 답답해서 개발을 못하겠으니 쓰는 것이고, 수 많은 자바개발자들과 DI에 매료된 사람들 또는 DI를 스스로 먼저 나서서 지원하는 각종 프레임워크 개발자들도 각자 뭔가 맘에 드는게 있으니 쓰는 것일 뿐이겠지.

DI원리를 적용하거나 말거나, DI를 프레임워크를 이용해서 개발하거나 말거나 상관하고 싶지는 않은데, 그래도 "우리는 꾸진 자바와 달리 DI를 언어가 해결해주니까 필요없다"는 얘기는 제발이지 안했으면 좋겠다. 내가 아는 한 DI를 언어차원에서 지원해주는 것은 NOOP 밖에 없다.

다이나믹 타이핑 언어에서의 DI에 관해서 나름 균형있게 잘 소개한 http://onestepback.org/articles/depinj/ 이라는 글도 흥미롭다. 물론 여기도 DI라는 용어를 DI프레임워크라는 것과 별 구분없이 사용하는 듯 하다. 재밌는 내용은 Ruby에서 DI가 많이 사용되지는 않는다고 하면서 그 이유로 다음 두가지를 들고 있는 것인데,

  • The dynamic nature of Ruby reduces the payoff
  • DI really becomes useful in really large projects
    • There aren’t that many really large Ruby projects.

언어적인 특성 어쩌고 하는 것들은 사실 대부분 테스팅(주로 mock)에 관한 것이라는 점도 좀 아쉽긴 하지만 아무튼 편하긴 하니가 그렇다 치고, 두번째 내용이 흥미롭다. DI는 대규모 프로젝트에서 유용해진다는 점이다. 그런데 루비 프로젝트는 그런 큰 규모의 개발이 별로 없다고. 대규모의, 그래서 많은 팀과 개발자들이 협력해야 하고, 그래서 어쩌면 평균적인 개발자들의 수준은 하향되는 구조에서 개발자들의 고급 코딩 능력에 의존될 가능성이 높은 루비와 같은 언어는 그다지 매력적이지 않은가보다. 자바라고 크게 다를 바는 없다고 생각되지만.

 

자바에서 DI가 더 인기있는 이유에 대해서 최신 DI경향을 가지고 생각해볼 필요가 있다고 생각한다. 원래 스프링의 DI설계모델은 XML이었다. XML에 모든 DI정보가 담겨 있었다. 그런 것이 이제는 구글주스의 등장과 스프링의 발전, 애노테이션 기반의 표준 모델에 의존적인 씸의 등장 등에 따라서 점차로 autowiring이라 불리는 자동DI쪽으로 설정방법이 많이 기울어져 가는 것 같다.

스프링의 @Autowired는 이전 XML에서 지원하던 byType방식의 autowiring과 달리 fine-grained된 타입 방식으로 DI후보를 자동으로 찾아준다. 매우 매력적이고 편하며 간단하다. XML조차 아예 필요없을 수도 있다. 과도한 설정파일 관리에서 해방되면서도 지능적으로 DI가 가능하다는 점 덕분에 최신 스프링버전의 적용 프로젝트들은 거의 대부분 애플리케이션 코드 레벨은 @Autowired를 비롯한 애노테이션 방식의 자동-와이어링 기법을 이용한다.

그런데 바로 이 @Autowired와 같은 자동 DI 후보를 찾는 기술은 스태틱 타입 언어이기 때문에 가능한 것이다. 자바와 같은 스태틱 타입언어는 툴링(tooling)에서 큰 장점이 있어서 다이나믹 타입 언어보다 우위에 있을 수 있다는 로드 존슨의 InfoQ 패널토의 시간의 발언이 생각난다. 다이나믹 타입언어는 DI후보를 자동으로 찾기가 매우 어렵다. 너무 유연해서 다이나믹하게 만들어지는, 또는 필요한 메소드 호출만 가능하면 주입이 가능한 언어이니 프레임워크가 자동으로 DI후보 하나를 찾아서 대입해준다는 것이 근본적으로 불가능하다. 루비 지원 IDE들이 리팩토링에 취약한 것도 마찬가지 이유이다.

그래서 다이나믹 타입 언어는 코드에 의한 adhoc DI에는 강력하지만, 반면에 애플리케이션 전반에 걸친 DI설정을 손쉽게 적용하기 위한 autowiring에는 취약한 것이다. 장점과 단점을 다 가지고 있는데, 본격적인 DI 프레임워크 적용으로 보자면 단점이 더 크다. 그래서 XML과 같은 명시적인 DI설정을 가지는 구조가 그나마 유일한 방법이고, 그런 부가적인 설계정보를 가진 프로그래밍 모델을 굳이 필요로 할 만큼 DI에 푹 빠지지 않는 이상 많이 사용하지 않는 것이 당연할지도 모르겠다.

 

그렇다면 과연 자바는 DI를 잘 사용하고 있을까? DI와 DI프레임워크(도구)를 구분해서 생각해야 한다는 점은 사실은 이런 위험성이 있다고 볼 수도 있다. DI프레임워크를 사용하지만 DI는 하지 않는 그런 문제도 있다는 말이다. DI는 객체지향설계의 유연성을 극대화 하기 위한 기법이다. 하지만 DI프레임워크를 사용하면서도 여전히 제대로된 객체지향설계는 없고, 기계적인 3-tier 컴포넌트에 DI 적용이 전부라면, 사실은 DI를 제대로 하고 있다고 말할 수 없다. 스프링을 백날 써봤자, 제대로된 클래스 설계와 적절한 분리, 유연한 합성구조 설계 등이 뒤따르지 않는다면 스프링의 철학과 목적에 부합하는 사용을 하고 있지 않다는 얘기다.

고객관리 서비스 클래스면 오로지 그 하나의 클래스에 자주 변하는 정책과 각종 인벤트시 처리와 잘 변하지 않는 고객관리의 기본 로직을 한데 뭉텅이로 넣어도 된다고 생각하고, SpringMVC의 컨트롤러는 스프링이 제공해주는 확장포인트 외에는 아무리 반복적이고 모듈화가 가능하며, 자주 변경되는 코드가 들어가도 그냥 복사해서 사용하고 마는 것이라면 그게 무슨 스프링이고 DI적용이란 말인가. 그런식으로 만들어 놓고 스프링 컨설팅을 한다고 다니는 사람들을 보면 정말 씁쓸하다.

 

DI의 특별한 적용사례의 한가지인 AOP(AOP를 포함해서 스프링의 모든 기술은 다 DI가 그 원리이다)에 대해서도 할 얘기가 있지만 너무 길어져서 여기서 끝.

Related posts:

  1. Dependency Injection의 Dependency란 무엇인가?
  2. Dependecy Injection에는 Prototype Scope가 없다
  3. 마이크로 DI(dependency injection)
  4. Dependency Injection 표준화?
  5. JSR-330 Dependency Injection for Java 최종 승인
  6. Code Organization & Cyclic Dependency Problem
  7. GoF 디자인 패턴에서 느끼는 DI의 향기
  8. EJB3의 Dependency Injection
  9. Spring 3.0 (53) Spring Dependency Matrix 업데이트
  10. Spring 3.0 (42) Spring Dependency Matrix 업데이트
  11. Spring 3.0 (7) Spring 3.0 Dependency Matrix
  12. Spring 3.0 (60) 클래스패스 리소스를 지정할 때 주의사항과 팁
  13. Spring 3.0 (14) Context Support 모듈의 선택 라이브러리 분석
  14. 스프링 3.1 (6) web.xml의 활성 프로파일 설정
  15. DI와 인터페이스

Facebook comments:

to “DI의 본질 – 다이나믹 (타입) 언어는 Dependency Injection이 필요없는가?”

  1. mbt sport 2 DI의 본질 – 다이나믹 (타입) 언어는 Dependency Injection이 필요없는가? » Toby’s Epril

  2. mbt-shop DI의 본질 – 다이나믹 (타입) 언어는 Dependency Injection이 필요없는가? » Toby’s Epril

  3. priligy belgique
    With Google’s technique of not paying attention intently on Meta tag, you ought to pay considerably more awareness of label tag on the homepage. The first 66 figures are showcased in the major search engines rankings, making this where by your concentrate should rest. You should sum up what your online business is about from the very beginning. Help save the fluff and obtain instantly to the great things.
    super kamagra kaufen
    A food items processor chip can make existence with rheumatoid arthritis definitely, simpler and less hazardous. Rather than wielding a blade for cutting up, work with a foods central processing unit to make the task much more workable. A meals processor chip tends to make a lot of home tasks much easier and arthritic fingers and hands and fingers will take advantage of the warm, soapy water accustomed to clear the decreasing blade, plastic material dish and cover.
    viagra original
    Always employ the identical type of typefaces so that guests to your website don’t come to be agitated by reading through several types of typefaces. You want customers to read through the site easily so that they can just focus on the materials on the website and precisely what the web site offers.
    levitra kopen

  4. viagra kokemuksia
    To aid elevate the fog off of depression it is very important to find the support you require. It really is challenging to maintain viewpoint and maintain the effort that is required to overcome major depression, when you are performing it by yourself. Loneliness and solitude make major depression even worse, so retaining partnerships close up and staying involved with social activities is important.
    cialis fass
    You can include life and colour to any room by just incorporating potted plants. Try out different types that grow in a variety of colors to match with all the design of your space and you have a quick straight away from a magazine seem. Greenery within the bathroom is especially wonderful if it is fragrant.
    cialis 20 mg ireland
    While you era your skin layer can grows more susceptible to the sun’s harshness. Try to goal activities that limit your exposure to sunshine. Wear a hat when walking or garden, and before you go out in the sunshine, handle the skin liberally with a great SPF sunscreen in order to avoid UV injury.
    Cialis lilly

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha