열렬히.뛰기

DI 이해해보기

웹 프로그래밍 > Spring > DI 이해해보기

IOC를 코드화하는 방법 중 하나가 DI라고 했다.

DI 알아보기

일단 말이 어렵다. 의존성주입한다?

  • 의존성 : 위에서 이야기한 한 객체 안에 다른 객체가 들어있는 상황을 의미
  • 주입 : 스프링 컨테이너가 객체 안에 새로운 객체를 넣어준다는 의미

객체를 넣을 때 사용하는 특별한 어노테이션이 존재한다.

Autowired

DI를 구현하는 과정에서 어노테이션 @Autowired가 반드시 들어간다.

java
@Service
public class MyService {
    private final MyRepository repository;

    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }
}

@Autowired 키워드가 들어가 있으면, 스프링 컨테이너가 주입해야 할 객체(=Bean)을 넣을 준비를 한다고 생각하면 됨.

그럼 스프링 컨테이너는 뭘 보고 빈 객체(=Bean)을 미리 만드는가?

  • 설정 파일(예: @Configuration, @ComponentScan 등), 어노테이션(예: @Service, @Repository, @Component, @Controller 등)

의존성 주입 과정

  1. Myservice라는 객체는 repository라는 객체에 의존하고 있다. repository가 있어야, Myservice가 제대로 작동할 수 있다.

  2. @Autowired를 통해서 스프링 컨테이너 안에서 이미 만들어져 있던 repository 객체를 전달받는다.

  3. Myservice 객체의 생성자를 통해 repository 객체가 Myservice 객체 안으로 들어간다.

DI의 방법

DI를 구현하는 3가지 방법을 알아보자.

생성자 주입 (Constructor Injection)

java
public class MyService {
    private final MyRepository repository;

    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }
}

주입해야 할 객체를 생성자를 통해 넣는 방식.

생성자가 1개라면, @Autowired 어노테이션을 생략할 수 있음.

모든 의존성을 주입받아 불변성을 유지할 수 있고, 필수 의존성을 강제할 수 있습니다. 또한, 테스트가 용이하고, 순환 참조 방지에 도움이 됩니다.

세터 주입 (Setter Injection)

java
public class MyService {
    private MyRepository repository;

    @Autowired
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
}

주입해야 할 객체를 setter()를 통해 넣는 방식.

의존성을 선택적으로 주입해야 하거나, 필수적이지 않은 의존성을 주입할 때 유용.

  • 의존성이 선택적이다? 객체 안에 객체 중 꼭 필요한 경우가 아닌 경우를 의미.

필드 주입 (Field Injection)

java
public class MyService {
    @Autowired
    private MyRepository repository;
}

주입해야 할 객체를 객체 선언 과정에서 넣는 방식.

간단하지만 테스트와 유지보수에 불리하므로, 실무에서는 잘 사용하지 않는 편.