DI , IoC

KingDoor·2022년 11월 7일
0

DI

DI - Dependency Injection
의존하는 클래스에 대한 인스턴스를 직접 생성하지 않고, 컨테이너로부터 생성된 빈을 setter나 생성자를 통해 외부로부터 주입받는 것을 의미한다. DI를 사용하면 결합도가 낮아진다.

그로 인해 코드 수정이 쉬워지며, 테스트 코드 작성도 쉬워진다. IoC를 실현하는데 DI가 필수이며 IoC를 사용하면 객체 생명 주기 같은 프로그램 제어권을 프레임워크가 관리하도록 넘길 수 있다. 스프링 프레임워크 버전 4.3 이후에는 @Autowired도 생략되면서 생성자에 사용한 Bean만 선언하면 된다.

의존성 주입(DI) 을 사용하는 이유

  • 재사용성을 높여준다.
  • 테스트에 용이하다.
  • 코드를 단순화 시켜준다.
  • 사용하는 이유를 파악하기 수월하고 코드가 읽기 쉬워지는 점이 있다.
  • 종속성이 감소하기 때문에 변경에 민감하지 않다.
  • 결합도(coupling)는 낮추면서 유연성과 확장성은 향상 시킬 수 있다.
  • 객체간의 의존관계를 설정할 수 있다.
  • 객체(A)가 다른 객체(B)의 기능을 필요로 해서 생성하는 경우, A는 B를 의존하고 있다고 말할 수 있다.

직접적으로 클래스 내부에서 다른 객체를 생성하는 경우 결합도가 높은 코드가 되는데, 이후에 유지보수 측면에서 이런 코드는 적합하지 않은 코드이다.

스프링은 결합도는 낮고 응집도를 올릴 수 있는 기능을 제공하는데, 어노테이션을 통한 DI주입을 간편하게 만들어준다.

DI code

public static void main(String[] args) {
    Person person = new Worker();
    Company company = new CompanyImpl(person);
}

위의 예제는 DI(의존성 주입)의 예제이고, 생성자를 통해 외부에서 객체를 주입하고 있다.

IoC

말 자체는 어렵게 들릴 수 있지만, 위에서처럼 직접적으로 의존성을 만들지 않고, 외부에서 의존성을 가져오는 경우를 말합니다.

즉, 밖에서 나에게 의존성을 주입해주는 것을 DI(Dependency Injection) 라고 합니다. 따라서 DI는 IoC의 일종이라고 생각하시면 됩니다.

Bean

스프링 IoC 컨테이너가 관리하는 객체들을 Bean 이라고 부릅니다. 스프링은 이러한 Bean들의 의존성을 관리하고, 객체를 만들어 주며, Bean으로 등록을 해 주고, 이렇게 만들어진 것들을 관리합니다. 개발자가 이 부분까지 신경쓰지 않아도, 프레임워크가 알아서 해 주는 것입니다.

그리고 스프링 IoC 컨테이너가 위와 같은 관리를 해 줍니다. 이러한 Bean들을 담고 있는 스프링 IoC 컨테이너는 두 가지 중 하나를 사용합니다.

  • ApplicationContext 혹은 BeanFactory

ApplicationContext는 BeanFactory를 상속받으므로 둘 다 같은 일을 하는 것임
이러한 스프링에서의 의존성 주입은 반드시 Bean으로 등록된 객체들 끼리만 가능합니다. 스프링 IoC 컨테이너는 Bean으로 등록되지 않은 객체에는 의존성 주입을 해 주지 않습니다.

  • IntelliJ 에서는 Bean 인 경우 아래 사진처럼 왼쪽에 아이콘으로 표시해 줍니다.
  • 위에서 예시를 들었듯, OwnerController 생성자에서 의존성 주입이 일어나고 있습니다.
  • 그러면 OwnerController, OwnerRepository 모두 Bean이어야 할 것입니다.

Bean으로 등록하는 방법은?

그러면 특정 객체를 Bean으로 등록하는 방법은 무엇이 있을까요?

Component Scanning

  • @Component Annotation을 활용합니다.
  • 개발자가 직접 작성한 Class를 Bean으로 등록해줄 때 사용합니다.
  • 여러 인터페이스들을 라이프사이클 콜백이라고 부르는데, @Component 어노테이션이 붙어 있는 모든 클래스들을 찾아, 그 클래스의 인스턴스를 만들고, Bean으로 등록해 주는 복잡한 작업을 하는 어노테이션 처리기가 스프링에 있습니다.

Pet Clinic 프로젝트에서 main 시작 부분을 보겠습니다.

@SpringBootApplication 어노테이션이 붙어 있는데, 이를 정의한 곳으로 가 보면..

@ComponentScan 어노테이션이 붙어있음을 확인할 수 있습니다.

즉, ComponentScan 은 어느 지점부터 컴포넌트를 찾아보라고 알려 주는 것인데, 이것을 사용한 SpringBootApplication 어노테이션이 PetClinicApplication 클래스에 붙어 있습니다.

따라서, 이 PetClinicApplication 클래스부터 하위 모든 패키지들을 훑어보면서 @Component 어노테이션을 활용한 모든 클래스들을 찾고, Bean으로 등록하게 됩니다.

예를 들어 OwnerController를 살펴볼까요? 앞서 IntelliJ에서 Bean으로 등록되었다는 표시를 확인할 수 있었는데요. @Controller 어노테이션이 붙어 있었습니다.

그러면 이 @Controller 를 정의한 곳으로 가 보겠습니다.

위처럼 @Component 어노테이션이 붙어있음을 알 수 있습니다.

따라서 스프링은 OwnerController가 @Component 어노테이션을 활용했으므로 이를 Bean으로 등록해 준 것입니다.


profile
백엔드 지망하는 취준생 입니다!

0개의 댓글