DI 패턴을 사용하면 객체 간의 결합도(coupling)를 낮출 수 있어서 코드의 유연성과 확장성이 향상됨. 새로운 의존성이 추가되거나 변경되더라도, 이를 관리하는 코드를 수정해야 하는 경우를 최소화할 수 있음.
DI 패턴을 사용하면 의존성을 주입하는 것이 가능하기 때문에 테스트 용이성이 향상됨. 특정 의존성에 대한 가짜(Mock) 객체를 주입하여 테스트를 수행할 수 있어 객체 간의 상호작용을 검증하거나, 에러를 찾아내는 등의 작업을 보다 쉽게 수행할 수 있음.
DI 패턴을 사용하면 의존성을 객체 내부에서 생성하는 것이 아니라 외부에서 관리하기 때문에 객체 간의 의존성이 줄어들어, 코드의 재사용성이 높아짐. 이를 통해 코드 중복을 줄이고, 개발 생산성을 향상시킬 수 있음.
DI 패턴을 사용하면 의존성이 주입되는 과정이 명시적으로 표현되기 때문에 코드의 가독성이 향상되어 코드의 이해와 유지보수가 용이.
의존성이 외부에서 관리되어 수정해야 하는 경우 해당 코드만 수정하여 코드 변경 범위를 최소화할 수 있어 코드의 유지보수성이 향상.
객체를 생성할 때 해당 객체의 필수적인 의존성을 생성자의 파라미터를 통해 전달받는 방식으로 의존성을 객체 생성 시점에 모두 전달받기 때문에 객체 생성 후에는 의존성을 변경할 수 없음. 생성자 주입은 객체가 불변성을 보장하고, 필수적인 의존성을 놓치지 않도록 강제할 수 있으므로 안정적인 DI를 구현할 수 있음.
public class UserService {
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// UserRepository를 사용하는 메서드
}
Setter 메서드를 통해 의존성을 주입하는 방식으로 생성자 주입과 달리 선택적인 의존성 주입이 가능하나 Setter 주입을 사용하면 의존성 주입이 이루어지지 않은 상태에서 객체가 생성되어 NullPointerException 등의 예외가 발생할 수 있음.
public class UserService {
private UserRepository userRepository;
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
// UserRepository를 사용하는 메서드
}
생성자나 setter 메서드가 아닌 필드에 직접 의존성을 주입하는 방식으로 코드가 간결해지는 장점이 있지만, 객체의 불변성을 보장할 수 없으며 NullPointerException 등의 예외가 발생할 가능성이 있음.
public class UserService {
@Autowired
private UserRepository userRepository;
// UserRepository를 사용하는 메서드
}