본문 바로가기
스프링

IOC/DI - 제어의 역전/의존성 주입

by 진믈리 2024. 7. 7.

1. 의존성이란?

먼저 IOC와 DI를 설명하기 전에 의존성이란 무엇일까? 예를들어 A객체와 B객체가 있다고 하자 그런데 A객체를 사용하기위해 B객체가 필요하다면 그것은 A객체가 B객체에 의존한다고 한다. 쉽게 생각하면 의존성은 new 다.! A객체를 사용하기 위해 다른 객체를 new로 생성해야한다면 A객체는 생성된 객체에 의존하게 된다. 

class ClassA{
    ClassB b = new ClassB();
}

class ClassB{
    String my;
    ClassB(){
        this.my = "ClassB";
    }
}

 

2. DI - 의존성 주입이란?

위에서 의존이란 new 라고 했다. 그렇다면 의존성주입이란 무엇일까? 다시 쉽게 생각하면 외부에서 new를 주입시켜준다고 생각해보자 위의 예시코드에서는 ClassA 클래스 내에서 직접 new로 ClassB를 생성했다. 이번에는 반대로 외부에서 주입시켜 보겠다.

class ClassA{
    ClassB b;
    ClassA(ClassB b){
        this.b = b;
    }
}

class ClassB{
    String my;
    ClassB(){
        this.my = "ClassB";
    }
}

 

코드를 확인해보면 이번에는 ClassA 가 ClassB를 직접 new로 생성하는 대신 외부 매개체에서 생성자를 통해 의존성을 주입받고 있다. 이처럼 A객체가 직접 의존성을 생성하지 않고 외부에서 ClassB의 인스턴스를 생성해 의존성을 주입해 주는것을 의존성 주입이라 한다. 

 

3. IOC - 제어의 역전 

위에서 의존성 주입이란 외부 매개체에서 객체 인스턴스를 생성후 주입해주는 것을 의존성 주입이라 했다. 그렇다면 new! 인스턴스를 생성해주는 매개체는 무엇일까? 바로 ioc 컨테이너다. 물론 개발자가 직접 의존성을 제어 할 수도 있지만 스프링 프레임워크에서는 ioc컨테이너가 개발자에게서 일임받은 제어권을 사용하여 의존성을 관리하고 인스턴스를 생성하여 주입해주고 나중에는 메모리를 해제하는 역할까지 해준다.

이처럼 개발자가 직접 의존성을 제어하던것을  ioc컨테이너에 제어권을 일임 또는 빼앗기게 되어 제어의 주체가 개발자가 아니게 된것을 제어의 역전이라고 한다.

 

4. @Autowired를 통한 의존성 주입

스프링에서는 ioc컨테이너가 제어권을 일임받아 의존성을 관리해준다고 했다. 그렇다면 어떻게 ioc컨테이너가 의존성 관리를 해 주는 것일까? 스프링의 속성 주입 방법 중 하나인 @Autowired를 활용하는 방법을 알아보자.

4-1. 필드주입

@Component
public class ClassA {
    @Autowired
    public ClassB classb;
}

필드주입은 필드에 직접 의존성을 주입해 주는 방식이다. 코드가 간결하지만 가장 비추천 하는 방식이다.

외부에서 의존성 주입 없이 인스턴스화 될 가능성도 있고 불변성을 보장하기 어렵다. 따라서 테스트 코드를 작성하는데 어려움을 겪을수 있다.

4-2 세터주입

@Component
public class ClassA {
    private ClassB classb;

    @Autowired
    public void setMyClassB(ClassB classb) {
        this.classb = classb;
    }
}

세터주입은 세터 메서드를 통해 의존성을 주입해 주는 방식이다. 

의존성 주입이 필수 적이지 않고 선택적으로 주입할 수 있다. 다만 개발자가 수동적으로 세터메서드를 호출해야하기에 의존성이 주입되지 않은채로 사용될수 있다. 

테스트 코드 작성시에는 대상 객체에 의존성을 주입하기 용이하여 편리하다.

4-3 생성자주입

@Component
public class ClassA {
    private final ClassB classB;

    @Autowired
    public ClassA(ClassB classB) {
        this.classB = classB;
    }
}

생성자를 통해 의존성을 주입하는 방식이다.

의존성이 불변임을 보장하고 객체가 완전한 상태로 생성되기에 의존성이 주입되지 않아 발생하는 문제에 대해서 방지가 가능하다.

'스프링' 카테고리의 다른 글

인터셉터(Interceptor) 란?  (0) 2024.09.23
스프링부트 2.7x 버전과 스프링 부트 3.xx 의 차이  (0) 2024.09.07
싱글톤 패턴  (0) 2024.07.27
ResponseEntity와 Rest Api에 대하여  (0) 2024.07.18
@NotNull, @NotEmpty, @NotBlank  (0) 2024.07.11