만쥬의 개발일기

 

스프링 프레임워크(Spring Framework) 하면 반드시 알아야 하는 개념이 바로 DI, IoC이다.

DI는 의존성 역전으로, 클린 아키텍쳐를 읽으면서도 많이 배우고 개념을 다져왔는데, IoC에 대해서는 아직 잘 모르는 것 같아서

따로 정리해본다.

 

IoC는 스프링 뿐만 아니라 다른 프레임워크에서도 사용되는 범용적인 개념이다.

왜 IoC라는게 생겼을까? 무엇을 제어하고 왜 역전이 필요한 것인지, 천천히 알아보자.

 

IoC의 Control, 제어란?

여기서 제어라는건 "객체에 대한 주도권을 가지고 있다"라고 생각하면 좋다.

 

자바는 객체지향 프로그래밍 언어이고, 모든 객체는 생명주기(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방식을 사용하는 이유는 뭘까?

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() 같은 코드를 써주야겠지만, 스프링의 Autowired 어노테이션을 통해 해당 문제를 간편하게 해결할 수 있다!

 

저 ProfileService 객체가 한곳에만 쓰인다면 모르겠지만..

만약 100곳 1000곳이 넘는곳에서 사용된다면 어떨까?

그리고 중간에 객체에 변경이 일어나게된다면?

 

이렇듯 Controller, Service 등을 담당하는 특정 객체의 생명주기는 비즈니스로직과 크게 상관이 없는대신, 직접 관리하기가 굉장히 어렵다.

 

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

 

그렇다고, 모든 객체의 생명주기를 스프링 컨테이너가 관리하지는 않는다.

보통은 위에서 얘기했던것처럼 Controller, Service 등의 역할을 담당하는 특정 객체들만 관리해준다.

이처럼 스프링 컨테이너가 관리하는 자바 객체를 바로 Bean 이라고 하고,그리고 이 Bean 을 등록하는 방법은 여러가지가 있는데, 다음 포스팅을 참고하자.

 

[Java 기술 면접 대비] - 4. @Bean VS @Component

Spring으로 개발을 하다보면 @Bean과 @Component를 언제 써야할지 헷갈릴때가 있다. 둘다 목적이 명확하지 않은 Bean을 생성할때 사용하는 어노테이션인데, 정확히 차이를 짚고 넘어가보자. @Bean VS @Compo

kangmanjoo.tistory.com


스프링 컨테이너(IoC 컨테이너)의 종류

 

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

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

 

결론

결국 IoC를 한 마디로 정의하면, 객체의 생명주기 사용자가 아닌 프레임워크가 컨트롤 하는 것이다.

 

 

Reference

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

profile

만쥬의 개발일기

@KangManJoo

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!