😥 문제
생성자 주입(Constructor Injection)을 사용해야 하는 이유
- 불변성(Immutability): 생성자 주입은 객체가 생성될 때 모든 의존성이 설정되기 때문에, 객체가 불변(immutable) 상태가 됩니다. 이는 객체가 생성된 이후에는 의존성이 변경되지 않음을 보장하여 코드의 안정성을 높입니다.
- 강한 의존성 명시: 생성자 주입을 사용하면 필요한 의존성을 생성자 매개변수로 명시하게 되어, 객체가 어떤 의존성을 필요로 하는지 명확하게 드러납니다. 이는 코드의 가독성을 높이고, 잘못된 사용을 방지합니다.
- 테스트 용이성: 생성자 주입은 의존성을 주입하기 위해 별도의 설정이 필요 없으므로 단위 테스트 작성이 용이합니다. Mock 객체나 Stub 객체를 생성자에 전달하여 쉽게 테스트할 수 있습니다.
- 순환 의존성 방지: 생성자 주입을 사용하면 순환 의존성(Circular Dependency) 문제를 사전에 발견할 수 있습니다. 컴파일 시점에 순환 의존성을 체크할 수 있어 런타임 오류를 방지할 수 있습니다.
다른 주입 방식들의 단점
- 세터 주입(Setter Injection):
- 객체 상태 불명확성: 객체가 생성된 후에도 세터 메서드를 통해 의존성이 변경될 수 있기 때문에, 객체 상태가 불명확해질 수 있습니다. 이는 객체의 불변성을 해치며, 디버깅과 유지보수를 어렵게 만듭니다.
- 불완전한 상태 가능성: 세터 주입을 사용하면 의존성이 설정되지 않은 상태로 객체가 사용될 수 있는 위험이 있습니다. 이는 NPE(NullPointerException)와 같은 런타임 오류를 발생시킬 수 있습니다.
- 순환 의존성 문제: 세터 주입에서는 순환 의존성을 컴파일 시점에 발견하기 어렵습니다. 이는 런타임 시에만 문제가 드러날 수 있어, 디버깅이 어려울 수 있습니다.
- 필드 주입(Field Injection):
- 캡슐화 위반: 필드 주입은 주로 프레임워크에서 리플렉션을 사용하여 의존성을 주입합니다. 이는 객체의 캡슐화를 위반하여 객체의 내부 상태를 외부에서 변경할 수 있게 만듭니다.
- 테스트 어려움: 필드 주입은 테스트 시에 의존성을 설정하기 어렵습니다. Mock 객체나 Stub 객체를 주입하려면 리플렉션을 사용해야 하며, 이는 테스트 코드의 복잡성을 증가시킵니다.
- 의존성 불명확성: 필드 주입을 사용하면 클래스 외부에서 어떤 의존성을 필요로 하는지 명확하게 알 수 없습니다. 이는 코드 가독성을 저하시킵니다.
결론
생성자 주입은 객체의 불변성을 보장하고, 의존성을 명확하게 드러내며, 테스트를 용이하게 만들어줍니다. 반면에 세터 주입과 필드 주입은 객체 상태의 불명확성, 캡슐화 위반, 테스트의 어려움 등의 단점을 가지고 있습니다. 따라서, 의존성 주입 방법 중 생성자 주입이 가장 바람직한 선택으로 여겨집니다
🙌🏻 해결 방법
생성자 주입으로 사용하자
🔎 참고 자료
https://yaboong.github.io/spring/2019/08/29/why-field-injection-is-bad/