[Spring] IoC(Inversion of Control) - 제어의 역전 이란?
Spring

[Spring] IoC(Inversion of Control) - 제어의 역전 이란?

728x90

다른 유닛의 제어권을 뺏는 다크아칸의 "마인트 컨트롤" 스킬

스프링 프레임워크(Spring Framework) 하면 또 빼놓을 수 없는 단어가 DI, IoC가 아닐까 싶은데요!

 

IoC는 스프링 뿐만 아니라 다른 프레임워크에서도 사용되는 범용적인 개념입니다. 왜 IoC라는게 생겼을까요? 무엇을 제어하고 왜 역전이 필요한것일까요? 천천히 한번 알아봅시다.


여기서 제어는 무슨뜻인가요?

여기서 제어라는건 "객체에 대한 주도권을 가지고 있다"라고 생각하셔도 될 것 같습니다.

 

자바는 객체지향 프로그래밍 언어이고, 모든 객체는 생명주기(Life Cycle - 객제가 생성된 후 부터 폐기될 때까지의 기간) 를 가지고 있습니다.

 

일반적으로 프레임워크를 사용하지 않는다면, 자바 프로그램은 main() 메소드에서 시작해서 개발자가 미리 정한 순서를 따라 실행됩니다. 따라서 언제 객체를 생성할지, 폐기할지 등등 실행에 대한 모든 것이 전부 개발자에게 달려있죠. 즉 개발자가 모든 주도권을 가지고 있습니다.

 

예시를 한번 볼까요? 보통 자바로 객체의 메소드를 호출할때는 다음과 같은 과정을 거칩니다.

public class A {
    private B b = new B();
    b.method1();
}

위 같은 경우는 A객체가 B객체에 의존하고 있는 것이죠. 하지만 B객체 언제 생성이 되는지 명시가 돼있습니다. 명시가 돼있다는건 개발자가 이 객체의 생명주기를 직접 생각해야된다는 의미이기도 합니다.

 

하지만 스프링이 제공하는 @Autowired 어노테이션을 사용하면

public class A {
    @Autowired
    private B b;

    b.method1();
}

이렇게 객체를 초기화하거나 새로 생성하지 않고 사용할 수 있습니다.

 

오잉? 객체가 초기화가 안되었는데 어떻게 메소드를 호출하나요?? 저거 NPE 나는거 아는가요?

저 객체의 초기화는 스프링 프레임워크에서 알아서 해줍니다. 이게 바로 IoC의 핵심입니다. 개발자가 직접 객체가 언제 생성이 될지 결정하는 것이 아니라 스프링에서 (정확히는 스프링 컨테이너에서) 언제 생성이 될지 어떤 객체를 넣어줄지 스스로 관리가 됩니다.

 

따라서 개발자가 언제 객체가 생성되고 폐기되는지 제어하지 않고, 프레임워크가 제어권을 가져간다고 해서 제어의 역전 즉, Inversion of Control 이라고 불립니다.


왜 IoC 방식을 사용할까요?

여기서 드는 생각이 있을 것 같아요. 굳이 왜? 왜 프레임워크가 제어하도록 놔둬야하죠?

바로 개발자가 객체의 생명주기에 대한 세세한 걸 신경쓰지않고 비즈니스 로직에만 신경 쓸 수 있게 해주기 위함입니다.

 

예를 들어 스프링의 기본적인 mvc 패턴으로 개발된 controller 코드를 한번 봐볼까요?

@Controller
public class ProfileController {
    @Autowired
    private ProfileService profileService;
    
    @RequestMapping(value="/profile/create", method=RequestMethod.POST)
    public void createProfile(ProfileRequest profileRequest) {
        profileService.create(profileRequest);
    }
}

결국 자바는 main() 함수에서 부터 실행이되기 때문에 여기 ProfileController에서 createProfile 이라는 메소드가 실행되는 시점 전에는 ProfileService 객체가 생성되고 초기화 되어야할 것입니다. 만약 프레임워크를 안썼다고 한다면 개발자가 저 ProfileServie 객체가 사용되는 시점을 고려해서 profileService = new ProfileService() 같은 코드를 써주야겠죠.

 

저 ProfileService 객체가 한곳에만 쓰인다면 모르겠지만.. 만약 100곳 1000곳이 넘는곳에서 사용된다면 어떨까요..? 그리고 중간에 객체에 변경이 일어나게된다면요?? 이렇듯 Controller, Service 등을 담당하는 특정 객체의 생명주기는 비즈니스로직과 크게 상관이 없는대신, 직접 관리하기가 굉장히 어렵습니다.

 

그래서 IoC 로 인해 개발자는 비즈니스로직에만 집중할 수 있고, 나머지는 스프링 프레임워크에 포함된 스프링 컨테이너(IoC 컨테이너)가 알아서해주는 것이죠!

 

(오해) 오 그럼 스프링 컨테이너(IoC 컨테이너)가 모든 객체의 생명주기를 관리해주나요?? 쩐다..

아닙니다. 보통은 위에서 얘기했던것처럼 Controller, Service 등의 역할을 담당하는 특정 객체들만 관리해줍니다. 이처럼 스프링 컨테이너가 관리하는 자바 객체를 바로 Bean 이라고 합니다. 그리고 이 Bean 을 등록하는 방법은 여러가지가 있는데 새로운 글에서 다루도록 하겠습니다!


스프링 컨테이너(IoC 컨테이너)

IOC 컨테이너에는 2가지의 핵심적인 클래스가 있습니다.

  • BeanFactory:
    • 자바 객체(bean) 인스턴스를 생성, 설정, 관리하는 실질적인 컨테이너입니다.
    • getBean() 메소드를 통해 빈을 인스턴스화할 수 있습니다.
    • BeanFactory 컨테이너는 구동될 때 Bean 객체를 생성하는 것이 아니라, 클라이언트의 요청이 있을 때 Bean 객체를 생성합니다.
  • ApplicationContext:
    • BeanFactory를 상속받은 BeanFactory의 확장 버전입니다.
    • BeanFactory를 상속받은 interface이며, ApplicationContext 컨테이너는 구동되는 시점에 등록된 Bean 객체들을 스캔하여 객체화한다
    • 부가 기능과 빈을 지연 없이 얻을 수 있다는 장점으로 ApplicationContext을 실제 개발에서 주로 사용합니다.

 

출처:
- 스프링을 쓰는 이유 - 1. DI(의존 주입) + IOC(제어의 역전)
- IoC(Inversion of Control, 제어의 역전) / DI(Dependency Injection, 의존관계 주입)
- [Spring] 스프링 Bean, IoC Container, DI가 뭔데!!)
- [Spring] 스프링 컨테이너와 빈이란?
728x90