IoC(Inversion of Control)란

2022. 11. 1. 20:43Spring 기초

Ioc(제어의 역전)란 단순히 말하자면 프로그램의 제어 흐름 구조가 뒤바뀌는 것이다.

[일반적인 실행 흐름]
main() 메소드 등 시작 지점에서 다음에 사용할 오브젝트를 결정하고 생성 --> 생성한 오브젝트의 메소드를 호출 --> 해당 메소드 내에서 다음에 사용할 것을 결정하고 호출 --> 반복

제어의 역전은 이런 제어 흐름의 개념을 뒤집는다.
자신이 어떤 오브젝트를 사용할지 스스로 선택하지 않으며, 본인도 어디서 사용되는지 알 수 없다.
모든 제어 권한을 다른 대상에게 위임하기 때문이다.

서블릿을 예로 들면, 우리는 서블릿을 개발하고 서버에 배포할 수 있어도 그 실행을 우리가 직접 제어할 수 있는 방법은 없다. 대신 서블릿에 대한 제어권한을 가진 컨테이너가 적절한 시점에 서블릿 클래스의 오브젝트를 만들고 그 안의 메소드를 호출한다.

IoC의 간단한 예시를 살펴보자

아래 그림과 같은 관계도가 있다.

public class UserDaoTest {
    public static void main(String[] args) throws SQLException, ClassNotFoundException {
        //UserDao가 사용할 ConnectionMaker 구현 클래스를 결정하고 오브젝트를 생성한다.
        ConnectionMaker connectionMaker = new DConnectionMaker();
        
        //UserDao 생성 후 사용할 ConnectionMaker 타입의 오브젝트를 제공한다.
        // 결국 두 오브젝트 사이의 의존관계가 설정되는 효과가 나타난다.
        Userdao dao = new UserDao(connectionMaker);
        
        ...
    }
}

 

그런데 UserDaoTest는 UserDao가 잘 돌아가는지 테스트하기 위한 객체인데 직접 구체적인 클래스까지 생성하는 역할을 수행하고 있다.

이 상황에서 우리는 DaoFactory라는 객체를 추가해서, UserDao와 ConnectionMaker의 생성을 담당하도록 해보자

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

 

이제 UserDaoTest에서 객체를 생성하는 코드는 깔끔하게 지울 수 있다. 객체의 생성은 DaoFactory가 맡고 있기 때문이다.

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

 

변경된 설계도를 살펴보면 아래와 같다. 여기서 Client는 UserDaoTest가 되겠다. 

 

원래 ConnectionMaker의 구현 클래스를 결정하고 오브젝트 생성 제어권은 UserDaoTest에게 있었다. 하지만 이제는 DaoFactory가 공급해주는 것을 수동적으로 사용해야 할 입장이 됐다. 
자연스럽게 관심을 분리하고 책임을 나누는 과정 속에서 DaoFactory를 도입했던 과정이 바로 IoC를 적용하는 작업이었다고 볼 수 있다.

스프링은 IoC를 모든 기능의 기초가 되는 기반 기술로 삼고 있으며, IoC를 극한까지 적용하고 있는 프레임워크다.