Dependency Injection
스프링 프레임워크에서 의존성 주입(Dependency Injection) 이란 무엇이며, 이를 사용하는 이유는 무엇인가요?
의존성 주입(DI)은 객체 간의 의존 관계를 코드 내부에서 직접 생성하지 않고, 외부에서 주입하는 방식입니다. 스프링에서는 IOC 컨테이너가 객체를 관리하며, 필요한 의존성을 설정 파일이나 어노테이션 등을 통해 주입합니다. 이를 통해 결합도를 낮추고, 유연하고 테스트 가능한 구조를 만들 수 있습니다.
그렇다면 스프링에서 의존성 주입을 하는 방식에는 어떤 것들이 있고, 각각의 방식은 어떤 차이가 있을까요?
생성자 주입: 가장 권장되는 방식. 의존성을 명확히 표현하고, 불변성을 보장하며, 테스트와 유지보수가 쉬움.
setter 주입: 선택적 의존성에 적합. 테스트나 조건부 빈 주입 시 유용.
필드 주입: 가장 간단하지만, 테스트하기 어렵고 외부에서 주입 불가능. 주로 레거시 코드나 예제 코드에서만 사용 권장.
그렇다면, 스프링에서 생성자 주입을 가장 권장하는 이유는 무엇이고, 실무에서 setter나 필드 주입을 쓸 수밖에 없는 상황이 있다면 어떤 경우일까요?
setter나 필드 주입은 레거시 코드나 설정이 복잡한 외부 라이브러리에서 간혹 사용되며, 순환 참조 해결 목적이나 테스트에서 mocking을 위해 쓰이기도 함.
스프링에서 순환 참조(Circular Dependency)가 발생하면 어떤 일이 일어나고, 생성자 주입과 다른 주입 방식(setter, 필드)에서 각각 순환 참조가 발생했을 때의 차이점은 무엇인가요?
생성자 주입에서는 객체 생성 시점에 모든 의존성이 필요하므로, A → B → A와 같은 순환 구조가 있으면 BeanCurrentlyInCreationException
이 발생합니다. 필드나 setter 주입은 객체 생성 후 주입이 가능하기 때문에 순환 참조가 허용되지만, 이는 유지보수상 권장되지 않습니다.
스프링 5 이후에는 순환 참조에 대한 정책이 조금 강화되었는데, 스프링 부트 2.6부터는 순환 참조가 기본적으로 금지되어 있어.
이 설정을 다시 허용하려면 어떻게 해야 하고, 이렇게 순환 참조를 일부러 허용하는 것은 언제 필요한 걸까?
spring.main.allow-circular-references=true
설정을 통해 순환 참조를 임시로 허용할 수 있음.하지만 구조적으로 순환 참조가 있다면 설계를 다시 검토하는 것이 좋음.
의존성 주입과 관련해서, 스프링에서 @Autowired
외에도 사용할 수 있는 의존성 주입 어노테이션은 무엇이 있고, 그 차이는 무엇인가요?
@Autowired
외에도 사용할 수 있는 의존성 주입 어노테이션은 무엇이 있고, 그 차이는 무엇인가요?@Autowired
스프링 전용 어노테이션
필드, 생성자, 메서드에 사용 가능
기본적으로 타입 기준으로 주입함
@Inject
자바 표준 어노테이션 (JSR-330)
기능은 거의
@Autowired
와 동일함
@Resource
JSR-250에서 지원하는 어노테이션
이름 기준으로 주입
@Autowired
와는 다르게 동작할 수 있음 (이름 충돌 발생 가능성)
@Autowired
를 사용할 때, 주입 대상이 2개 이상이라서 스프링이 어떤 빈을 주입할지 모를 경우, 어떻게 해결할 수 있나요?
여러 해결 방법이 있는데, 가능한 한 다양하게 설명해줘!
@Autowired
를 사용할 때, 주입 대상이 2개 이상이라서 스프링이 어떤 빈을 주입할지 모를 경우, 어떻게 해결할 수 있나요?
여러 해결 방법이 있는데, 가능한 한 다양하게 설명해줘!@Qualifier
로 특정 이름 지정@Primary
로 우선 순위 지정@Resource
로 이름 기반 주입List/Map
형태로 여러 빈 주입 후 직접 분기 처리
Last updated