의존성 주입 방법

이진수·2024년 1월 30일
0

1. 의존성 주입이란?

외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로, 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮춘다.

  • 의존성: 한 객체가 다른 객체를 사용할 때 의존성이 있다고 표현한다.
public class Store {
    
    private Note note;
}

다음과 같이 Store 객체가 Note 객체를 사용하고 있는 경우, 우리는 Store 객체가 Note 객체에 의존성이 있다고 표현한다. ( Store -> Note )
그리고 두 객체 간의 관계를 맺어주는 것을 의존성 주입이라고 한다.


2. 의존성 주입이 필요한 이유

의존성 주입을 받으면 클래스 간의 결합도가 약해진다. 결합도가 약해진다는 것은 한 클래스가 변경될 경우, 다른 클래스가 변경될 필요성이 적어진다는 뜻으로 아래와 같은 이점이 생긴다.

1) 리팩토링이 쉬워진다.
2) 단위 테스트에 용이하다.
3) 인터페이스 기반으로 코드를 설계하여 유연하고 확장에 용이하다.


3. 의존성 주입의 3가지 방법

  1. 생성자 주입(Constructor Injection)
@Service
public class BookService {

    private final BookRepository bookRepository;
    
    @Autowired
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

클래스의 생성자가 하나이고, 그 생성자로 주입 받은 객체가 빈으로 등록되어 있으면 @Autowired 생략 가능하다. 다른 방법들과 다르게 final 선언이 가능해 런타임에 객체 불변성을 보장한다.


  1. 필드 주입(Field Injection)
@Service
public class BookService {

    @Autowired
    private BookRepository bookRepository;

final 키워드는 사용할 수 없다. 또한 코드는 간결하지만 외부에서 변경하기 힘들다는 단점이 있다.


  1. 수정자 주입(Setter Injection)
@Service
public class BookService {

    private BookRepository bookRepository;

    @Autowired
    public void setBookRepository(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

setter 메서드에 어노테이션을 붙이는 방법으로 어디서든 변경 가능하다는 단점이 있다.



4. 스프링에서 생성자 주입을 권장하는 이유

필드 주입과 수정자 주입은 의존성이 있는 객체가 생성되지 않아도 이를 포함하고 있는 객체가 생성 가능하여 런타임시에 오류를 인지하게 된다.
이에 반해 생성자 주입은 생성자에서 의존관계 주입이 일어나기 때문에 객체가 생성될 때 의존 객체의 null 여부를 검사해 컴파일시에 오류를 발생시킨다.
또한 생성자 주입을 사용하면 객체 간 순환참조를 하고 있는 경우에 스프링 애플리케이션이 구동되지 않는다. 컨테이너가 빈을 생성하는 시점에 객체 생성에 순환관계가 생기기 때문이다.

이처럼 생성자 주입을 사용하면 객체 간 순환참조를 하고 있는 경우에 스프링 애플리케이션이 구동되지 않는다.

profile
기록하는 개발자🧑🏻‍💻

0개의 댓글