IoC (Inversion of Control) 컨테이너에 대한 정리
Mike Spille의 IoC 컨테이너에 대한 글을 읽는 것을 계기로 정리를 해보자.
IoC에 대해 처음 듣게 된 것은, Rod Johnson이 TSS에 기고했던 Spring Framework 소개 글로 기억한다.
그러나, 실제로 어떤 이점을 주는지 이해하게 된 것은 Aslak Hellesoy의 인터뷰를 보고 나서다.
Aslak Hellesoy는 IoC 대신에 Dependency Injection이라는 말을 썼다. Mike Spille는 이 말에 대해 상당한 반감을 갖고 있지만(마틴 파울러가 마케팅적 목적으로 만들어낸 용어인 듯), 개인적으로는 IoC 보다는 Dependency Injection이 더 직관적이란 느낌을 받았다.
그러나, IoC는 컨테이너가 많은 부분 통제를 하게 된다는 것을 의미한다. 의존성뿐 아니라 객체의 생명주기까지, 따라서, 의존성 주입이라는 의미의 Dependency Injection은 IoC 컨테이너의 하나의 기능으로 보는 것이 적합한 것 같다. 그러나, 이런 개념적 논의는 어느 정도 수준이 된 이후에 개념만으로 실체를 논할 수 있는 단계에 이르러서나 의미가 있다. 나에게는 … 글쎄
IoC란 무엇인가?
l There's a container, which manages objects for you. I'll generally call it the IoC Container or just "the container".
l The container generally controls creation of objects. As I like to say, it does the new so you don't have to.
l The container resolves dependencies between objects it manages.
Mike Spille이 간략하게 정리한 것이다. 객체를 관리하고, 객체의 생성을 책임지고, 의존성을 관리하는 컨테이너. 깔끔하고 좋다. ^^;
Mike Spille이 예제를 들어 설명을 하고 있다. IoC를 사용하는 경우와 사용하지 않는 경우 코드에서 차이를 보이는 부분은 주로, 객체의 생성과 참조에 관련된 부분이다.
J2EE 프로그래밍을 하다 보면, 자원 관리나 동기성을 목적일수도 있지만, 의존성 관리를 위해서 new를 이용하여 객체를 생성하는 일에 제약을 받는다. 주로 쓰이는 방법은 싱클턴(Singleton)을 사용하는 경우와 JNDI나 서비스 로케이터(Service Locator)를 이용한 룩업(lookup) 방식이다.
public class ThreadPoolJobDispatcher implements IJobDispatcher { public ThreadPoolJobDispatcher (IEventManager eventManager_, ICacheManager cacheMan_) { // Initialize thyself! } public void dispatch (Job job_) { // Dispatch it! } }
위와 같은 코드를 위해서 싱글턴에서는 아래와 같은 코드가 IJobDispatcher tpDispatcher = new ThreadPoolJobDispatcher (DefaultEventManager.instance(), DumbMapCacheManager.instance());
룩업방식은 아래와 같은 코드가 필요하다. IJobDispatcher tpDispatcher = new ThreadPoolJobDispatcher ( (IEventManager)context.lookup ("eventManager"), (ICacheManager)context.lookup ("cacheManager"));
IoC를 사용하면 이러한 일들을 대신해주는 것이라고 이해할 수 있다.
1. The container is in charge of creating objects. It does the new so you don't have to.
2. The container is in charge of resolving dependencies for you
뒤에서 IoC 컨테이너가 실제로 구현하는 내용은 아래의 의사코드로 설명된다. IoCContainer container = new IoCContainer(); container.register (DumbMapCacheManager); container.register (DefaultEventManager); container.register (ThreadPoolJobDispatcher);
IJobDispatcher dispatcher = container.getMe (IJobDispatcher);
뒤이어 Mike Spille은 IoC 컨테이너를 비교하는데, 먼저 비교의 기준이 되는 척도를 다음과 같이 제시한다.
IoC 컨테이너 점검표(checklist)
l Control of instantiation of managed objects
l Resolves dependencies between managed objects
l Support for constructor or setter based injection
l Support for lifecycles
l Support for cyclical dependencies
l Configuration support
l Support for eager instantiation
대부분 앞에서 했던 이야기들이고, 마지막 eager instantiation은 서버 시작과 동시에 인스턴스가 미리 생성되어 있어야 하고, 가능하면 Lazy Loading도 지원하는 것이 중요하다는 것인듯하다. 자원의 효율적인 활용을 위해 Lazy Loading은 자주 강조되지만, 미리 인스턴스를 생성해놓는 것은 빠른 응답시간과 시스템 안정성을 보장할 수 있다.
이후에 Mike Spille은 세 개의 IoC 컨테이너를 비교하는데, HiveMind, Spring IoC, Pico인데, 상당히 편향성을 갖고 보고 있다. Dependency Injection이라는 용어를 대할 때부터 마틴 파울러와 ThoghtWorks에 대한 반감을 표명하고 있는데, Pico의 경우 ThoughtWorks 직원이 주축이 되어 개발하였기 때문에 악평을 하고 있다. 이런 태도로 인해서 구체적인 항목에 대해 과연 신빙성이 있는가 의심되기도 한다. ㅡㅡ; 이런 이유에 더하여 개인적으로 HiveMind와 PicoContainer를 잘 모르는 가운데 괜한 선입견만 갖게 될까봐 구체적인 내용은 살피지 않는다. 저자는 HiveMind를 좋아한다고 애초부터 분명히 하고 있고, Spring에 대해서는 호평을 하면서 Autowiring에 디폴트에 대해 흠이 있다고 지적하는데, 여기에 대해 수많은 방문자들이 비평을 가하고 있다. |