PengTory

[Spring] 오브젝트와 의존관계 (3) _ IoC 본문

Spring

[Spring] 오브젝트와 의존관계 (3) _ IoC

펭토리 2022. 10. 14. 01:04

IoC

IoC(Inversion of Control)라는 제어의 역전이라는 용어가 있다.

IoC가 무엇인지 살펴보기 위해 앞서 작성한 UserDao 코드를 좀 더 개선해보겠다.

 

오브젝트 팩토리

사실 앞서 DAO를 확장시키는 과정에서 넘어간 과정이있다. DAO를 깔끔하게 리팩토링하기 위해 클라이언트인 UserDaoTest에  어떤 ConnectionMaker 구현 클래스를 사용할지를 결정하는 기능을 넣은 것이다.

원래 UserDaoTest의 역할은 UserDao의 기능이 잘 작동하는지를 테스트하는 것이다. 그럼 지금까지 했던 것 처럼 책임이나 관심사를 분리해보자.

 

팩토리

팩토리는 객체의 생성 방법을 결정하고 그렇게 만들어진 오브젝트를 돌려주는 일을 하는 오브젝트이다. 오브젝트를 생성하는 쪽과 생성된 오브젝트를 사용하는 쪽의 역할과 책임을 깔끔하게 분리하려는 목적으로 사용하는 것이다.

public class DaoFactory {
    public UserDao userDao(){
        ConnectionMaker connectionMaker = new DConectionMaker();
        UserDao userDao = new UserDao(connectionMaker);
        return userDao;
    }
}

DaoFactory의 useDao의 메소드를 호출하면 DConnectionMaker를 사용해 DB 커넥션을 가져오도록 이미 설정된 UserDao 오브젝트를 돌려준다. 

public class UserDaoTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException{
        UserDao dao = new DaoFactory().userDao();
        // ...
    }
}

UserDaoTest는 이제 UserDao가 어떻게 만들어지는지 어떻게 초기화되어 있는지에 신경쓰지 않고 팩톨로부터 UserDao 오브젝트를 받아다가, 자신의 관심사인 테스트를 위해 활용하기만 할 수 있게 되었다.

 

DaoFactory를 적용한 구조를 위와 같은 관점으로 구분해 그림을 그리면 다음과 같다.

오브젝트 팩토리를 활용한 구조

DaoFactory를 분리했을 때 얻을 수 있는 장점은 매우 다양하다.

그 중 애플리케이션의 컴포넌트 역할을 하는 오브젝트와 애플리케이션의 구조를 결정하는 오브젝트를 분리했다는 것이 가장 큰 의미가 있다.

 

제어권의 이전을 통한 제어관계 역전

이제 다시 제어의 역전이라는 개념에 대해 알아보자. 제어의 역전이란 간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이다.

일반적으로 프로그램 흐름은 main() 메소드와 같이 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정하고, 결정한 오브젝트를 생성하고, 만들어진 오브젝트에 있는 메소드를 호출하고, 그 오브젝트 안에서 다음에 사용할 것을 결정하고 호출하는 방식의 반복이다.

 

그러나 제어의 역전이란 이런 제어 흐름의 개념을 거꾸로 뒤집는 것이다. 제어의 역전에서는 오브젝트가 자신이 사용할 오브젝트를 스스로 선택하지 않는다. 당연히 생성하지도 않는다. 또 자신도 어떻게 만들어지고 어디서 사용되는지를 알 수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임하기 때문이다.

 

스프링의 IoC

애플리케이션 컨텍스트와 설정정보

지금까지 IoC의 개념에 대해 대략적으로 알았으니 스프링을 사용해보자. DaoFactory를 스프링에서 사용이 가능하도록 변신시켜보려한다.

스프링에서는 스프링이 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 이라고 부른다.

스프링 빈은 스프링 컨테이너가 생성된 관계설정, 사용 등을 제어해주는 제어의 역전이 적용된 오브젝트를 가리키는 말이다.

스프링에서는 빈의 생성과 관계 설정 같은 제어를 담당하는 IoC 오브젝트를 빈 팩토리 라고 부르고 이를 좀 더 확장한 애플리케이션 컨텍스트를 주로 사용한다.

애플리케이션 컨텍스트는 별도의 정보를 참고해 빈의 생성 관계설정 등의 제어 작업을 총괄한다. 별도로 설정 정보를 담고 있는 무언가를 가져와 이를 활용하는 범용적인 IoC엔진 같은 것이라고 볼 수 있다.

 

DaoFactory를 사용하는 애플리케이션 컨텍스트

스프링이 빈 팩토리를 위한 오브젝트 설정을 담당하는 클래스라고 인식하기 위해서는 @Configuration이라는 어노테이션을 추가한다.

그리고 오브젝트를 만들어주는 메소드에는 @Bean이라는 애노테이션을 추가한다.

@Configuration
public class DaoFactory {
    @Bean
    public UserDao userDao(){
        return new UserDao(connectionMaker());
    }
    
    @Bean
    public ConnectionMaker connectionMaker(){
        return new DConectionMaker();
    }
}

 

애플리케이션 컨텍스트는 ApplicationContext 타입의 오브젝트이다. ApplicationContext를 구현한 클래스는 여러 가지가 있는데 DaoFactory처럼 @Configuration이 붙은 자바 코드를 설정정보로 사용하려면 AnnotationConfigApplicationContext를 이용하면 된다.

public class UserDaoTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException{
        ApplicationContext context = new AnnotationConfigApplicationContext(DaoFactory.class);
        UserDao dao = context.getBean("userDao", userDao.class);
        // ...
    }
}

getBean() 메소드는 ApplicationContext가 관리하는 오브젝트를 요청하는 메소드다. 

 

애플리케이션 컨텍스트의 동작방식

애플리케이션 컨텍스트가 동작하는 방식

오브젝트 팩토리에 대응되는 것이 스프링의 애플리케이션 컨텍스트다. ApplicationContext에는 DaoFactory와 달리 직접 오브젝트를 생성하고 관계를 맺어주는 코드가 없고, 그런 생성 정보와 연간관계 정보를 별도의 설정정보를 통해 얻는다. 때로는 외부의 오브젝트 팩토리에 그 작업을 위임하고 그 결과를 가져다가 사용하기도 한다.

 

DaoFactory를 오브젝트 팩토리로 직접 사용했을 때와 비교해서 애플리케이션 컨텍스트를 사용했을 때 얻을 수 있는 장점은 다음과 같다.

1) 클라이어트는 구체적인 팩토리 클래스를 알 필요가 없다.

2) 애플리케이션 컨텍스트는 종합 IoC 서비스를 제공해준다.

3) 애플리케이션 컨텍스트는 빈을 검색하는 다양한 방법을 제공한다.

 

스프링 IoC의 용어 정리

1) 빈: 빈 또는 빈 오브젝트는 스프링이 IoC 방식으로 관리하는 오브젝트라는 뜻이다.

2) 빈 팩토리: 스프링읜 IoC를 담당하는 핵심 컨테이너를 가리킨다. 빈을 등록하고, 생성하고, 조회하고 돌려주고, 그 외에 부가적인 빈을 관리하는 기능을 담당한다.

3) 애플리케이션 컨텍스트: 빈 팩토리를 확장한 IoC 컨테이너이다. 빈을 등록하고 관리하는 기본적인 기능인 빈 팩토리와 동일하다.

4) 설정정보/ 설정 메타정보: 스프링의 설정정보란 애플리케이션 컨텍스트 또는 빈 팩토리가 IoC를 적용하기 위해 사용하는 메타정보를 말한다.

5) 컨테이너 또는 IoC 컨테이너: IoC 방식으로 빈을 관리한다는 의미에서 애플리케이션 컨텍스트나 빈 팩토리를 컨테이너 또는 IoC 컨테이너라고도 한다. 후자는 주로 빈 팩토리의 관점에서 이야기하는 것이고, 그냥 컨테이너 또는 스프링 컨테이너라고 할 때는 애플리케이션 컨텍스트를 가리키는 것이라고 보면 된다.

6) 스프링 프레임워크: 스프링 프레임워크는 IoC 컨테이너, 애플리케이션 컨텍스트를 포함해서 스프링이 제공하는 모든 기능을 통틀어 말할 때 주로 사용한다.

 

 

[참고자료] 토비의 스프링 3.1 Vol.1 스프링의 이해와 원리