본문으로 바로가기


IoC란 간단하게 말하여 프로그램의 제어 흐름 구조가 바뀌는 것이다.

일반적으로, main() 같은 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정, 생성하고, 만들어진 오브젝트 내의 메소드를 호출하는 작업을 반복한다. 이런 구조에서 각 오브젝트느 프로그램 흐름을 결정하거나 사용할 오브젝트를 구성하는 작업에 능동적으로 참여한다.

즉, 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조이다.

 

이에 반하여 IoC는 제어 흐름의 개념을 거꾸로 뒤집는다. 오브젝트는 자신이 사용할 오브젝트를 스스로 생성하거나 선택하지 않는다. 그리고 자신이 어떻게 만들어지고 어디서 사용되는지 알 수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하는 것이다. 프로그램의 시작을 담당하는 main()같은 엔트리 포인트를 제외하면 모든 오브젝트는 이런 방식으로 위임받은 제어 권한을 갖는 특별한 오브젝트에 의해 결정되고 만들어지는 것이다.

 

위의 내용을 토대로 IoC를 요약하여 말하자면 아래와 같이 정의할 수 있다.

- 작업을 수행하는 쪽에서 Object 를 생성하는 제어 흐름의 개념을 거꾸로 뒤집는다.
- IoC 에서는 Object 가 자신이 사용할 Object 를 생성하거나 선택하지 않는다.
- 또한 Object 는 자신이 어떻게 생성되고 어떻게 사용되는지 알 수 없다.
- 모든 Object 는 제어 권한을 위임받는 특별한 Object 에 의해서 만들어 지고 사용된다. 

 

 

IoC 구현 방법

  • DL (Dependency Lookup)  - 의존성 검색
            저장소에 저장되어 있는 빈(Bean)에 접근하기 위하여 개발자들이 컨테이너에서 
    제공하는 API 를 이용하여 
            사용하고자 하는 빈(Bean) 을 Lookup 하는 것
  • DI (Dependency Injection) - 의존성 주입
            각 계층 사이, 각 클래스 사이에 필요로 하는 의존 관계를 컨테이너가 자동으로 연결해주는것
            각 클래스 사이의 의존 관계를 빈 설정(Bean Definition) 정보를 바탕으로 컨테이너가 자동으로 연결해 주는 것
            DL 사용 시 컨테이너 종속성이 증가하여, 이를 줄이기 위하여 DI를 사용
        Setter Injection - 인자가 없는 생성자나 인자가 없는 static factory 메소드가 bean을 인스턴스화 하기 위하여 
                              호출된 후 bean의 setter 메소드를 호출하여 실체화하는 방법
                              - 객체를 생성 후 의존성 삽입 방식이기에 구현시에 좀더 유연하게 사용할 수 있다.
                              - 세터를 통하여 필요한 값이 할당되기 전까지 객체를 사용할 수 없다.
                              - Spring 프레임워크의 빈 설정 파일에서 property 사용
  • public class SimpleMovieister{

    private MovieFinder movieFinder;  

    public void setMovieFinder(MovieFinder movieFinder){

    this.movieFinder = movieFinder;

    }

    }


        Constructor Injection - 생성자를 이용하여 클래스 사이의 의존 관계를 연결
                              - 생성자에 파라미터를 지정함으로 생성하고자하는 객체가 필요로 하는 것을 명확하게 알 수 있다.
                              - Setter메소드를 제공하지 않음으로 간단하게 필드를 불변 값으로 지정이 가능하다.
                              - 생성자의 파라미터가 많을 경우 코드가 복잡해 보일 수 있다.
                              - 조립기 입장에서는 생성의 순서를 지켜야 하기에 상당히 불편하다.
                              - Spring 프레임워크의 빈 설정 파일에서 constructor-arg 사용

    public class SimpleMovieister{

    private MovieFinder movieFinder;

    public SimpleMovieLister(MovieFinder movieFinder){

    this.movieFinder = movieFinder;

    }

    }

     

        Method Injection - Singleton 인스턴스와 Non Singleton 인스턴스의 의존 관계를 연결 시킬 필요가 있을 
                              경우 사용하지만, 많이 사용하지는 않는다.

     

     

    의존성 주입(DI)의 간단한 예제

     

    Setter Injection의 예제

    <bean id="exampleBean" class="examples.ExampleBean">
        <property name="beanOne"><ref bean="anotherExampleBean"/></property>
        <!-- setter injection using the neater 'ref' attribute -->
        <property name="beanTwo" ref="yetAnotherBean"/>
        <property name="integerProperty" value="1"/>
    </bean>

    <bean id="anotherExampleBean" class="examples.AnotherBean"/>
    <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

     

    public class ExampleBean {
        private AnotherBean beanOne;
        private YetAnotherBean beanTwo;
        private int i;

        public void setBeanOne(AnotherBean beanOne)
            this.beanOne = beanOne;

        public void setBeanTwo(YetAnotherBean beanTwo)
            this.beanTwo = beanTwo;

        public void setIntegerProperty(int i)
            this.i = i;
    }

     

     

    Constructor Injection의 예제

    <bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg>
        <constructor-arg ref="yetAnotherBean"/>    
               // <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg> 위와 동일
        <constructor-arg type="int" value="1"/>
    </bean>

    <bean id="anotherExampleBean" class="examples.AnotherBean"/>
    <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

     

    public class ExampleBean {
        private AnotherBean beanOne;
        private YetAnotherBean beanTwo;
        private int i;
        
        public ExampleBean(
            AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
            this.beanOne = anotherBean;
            this.beanTwo = yetAnotherBean;
            this.i = i;
        }
    }

     

     

    IoC 용어 정리

    bean - 스프링에서 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트

    자바빈, EJB 빈과 비슷한 오브젝트 단위의 애플리케이션 컴포넌트를 말한다하지만 스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 빈은아니다스프링의 빈은 스프링 컨테이너가 생성과 관계설정사용등을제어해주는 오브젝트를 가리킨다.


    bean factory - 스프링의 IoC 담당하는 핵심 컨테이너

    빈을 등록/생성/조회/반환/관리한다보통은 bean factory  바로 사용하지 않고 이를 확장한 application context  이용한다. BeanFactory  bean factory  구현하는 interface 이다. (getBean()등의 메소드가 정의되어 있음)

     

    application context - bean factory 확장한 IoC 컨테이너

    빈의 등록/생성/조회/반환/관리의 기능은 bean factory  같지만여기에 spring 각종 부가 서비스를 추가로 제공한다. ApplicationContext application context 구현해야 하는 interface이여, BeanFactory  상속한다.

     

    configuration metadata (설정정보/설정 메타정보)

    application context 혹은 bean factory  IoC 적용하기 위해 사용하는 메타정보

    스프링의 설정정보는 컨테이너에 어떤 기능을 세팅하거나 조정하는 경우에도 사용하지만 주로 bean  생성/구성하는 용도로 사용된다.

     

    container (IoC container)

    IoC 방식으로 bean 관리한다는 의미에서 bean factory  application context  가리킨다
    (spring container = application context) 
    application context
      자체로 ApplicationContext 인터페이스를 구현한 오브젝트를 가리키기도 하는데하나의 애플리케이션에 보통 여러개의 ApplicationContext Object 만들어진다이를 통칭해서 strping container라고 부를  있다.

    간단하게, 객체를 관리하는 컨테이너이다, 컨테이너에 객체를 담아 두고, 필요할 때에 컨테이너로부터 객체를 가져와 사용할 수 있도록 하고 있다.

     

    spring framework - IoC container, application context  포함해서 spring 제공하는 모든 기능을 통칭한다.

     

     

    클래스 호출방식

    일반적인 클래스 호출

    클래스내에 선언과 구현이 한몸이기때문에 다양한 형태로 변화가 불가능하다.

     

    인터페이스를 이용한 클래스 호출

    클래스를 인터페이스와 구현클래스로 분리를 하였다.
    구현클래스 교체가 용이하여 다양한 형태로 변화가 가능
    하지만 구현클래스 교체시 호출 클래스의 소스를 수정해야한다.

     

    팩토리패턴을 이용한 클래스 호출방식

    팩토리방식은 팩토리가 구현클래스를 생성하므로 클래스는 팩토리를 호출하는 코드로 충분하다.
    구현클래스 변경시 호출클래스에는 영향을 미치지 않고, 팩토리만 수정하면 된다.

    하지만 클래스에 팩토리를 호출하는 소스가 들어가야한다. 그것 자체가 팩토리에 의존함을 의미한다

     

    IoC를 이용한 클래스 호출 방식

    팩토리패턴의 장점을 더하여 어떠한것에도 의존하지 않는 형태로 구성이 가능하다.
    실행 시점에 클래스간의 관계가 형성이 된다. 
    즉 의존성이 삽입된다는 의미로 IoC를 DI(Dependency Injection) 라는 표현으로 사용한다.

     

    +

    자바가 등장하고 자바 기반으로 애플리케이션을 개발하기 시작하던 최초의 시기에는 자바 객체를 생성하고 객체간의 의존관계를 연결시키는 등의 제어권을 개발자가 직접 가지고 있었다.(new 연산자, 인터페이스 호출, 팩토리 호출방식으로 객체의 인스턴스를 생성) 그러나 서블릿, EJB가 등장하면서 개발자들의 독점적으로 가지고 있던 제어권이 서블릿과 EJB를 관리하는 컨테이너에게 넘어가 버렸다.

    (컨테이너 : 적절한 설정만 되어있다면 누구의 도움 없이도 프로그래머가 작성한 코드를 스스로 참조한 뒤 알아서 객체의 생성과 소멸을 컨트롤해준다.)

     객체에 대한 제어권이 컨테이너에게 넘어가면서 객체의 생명주기를 관리하는 권한 또한 컨테이너들이 전담할 수 밖에 없게 되었다. 이처럼 객체의 생성에서부터 생명주기의 관리까지 모든 객체에 대한 제어권이 바뀐것을 의미하는 것이 제어권의 역전, 즉IOC(Inversion Of Control) 이다.


    참조목록

    http://openframework.or.kr/framework_reference/spring/ver2.x/html/beans.html
    http://lefthand29.blogspot.com/2012/02/ioc-inversion-of-control-spring-ioc_22.html#!/2012/02/ioc-inversion-of-control-spring-ioc_22.html

    http://blog.daum.net/kitepc/557
    http://www.javajigi.net/pages/viewpage.action?pageId=5614#SpringIoC%EA%B0%9C%EB%85%90%EB%B0%8F%ED%99%9C%EC%9A%A9%EB%B0%A9%EC%95%88-1.IoC%EC%9D%98%EA%B0%9C%EB%85%90
    http://code.google.com/p/developerhaus/wiki/TobySpring_10#10.2_IoC/DI를_위한_빈_설정_메타정보_작성

    http://trypsr.springnote.com/pages/251122


    출처

    http://isstory83.tistory.com/91