본문 바로가기
Spring Boot 개념 정리

의존성 주입(DI) 정리 및 후기

by 반오십 코린이 2023. 9. 1.
728x90
필드 주입

 

@Controller
Public class Controller{

	@Autowired
	private Service service;
        
}

 

  • 코드가 간결하지만 외부 변경 불가
  • 테스트하기 어렵다.
  • final을 못 쓴다.
  • DI에 지나친 의존성

수정자 주입

 

@Controller
Public class Controller{

    private Service service;
    
    @Autowired
    public void setController(Service service){
    	this.service = service;
    }
        
}

 

  • 선택, 변경 가능성이 있는 의존관계
  • 객체가 변경될 필요성이 있을 때만 사용

생성자 주입

 

@Controller
Public class Controller{
	@Autowired
	private Service service;
    
    public Controller(Service service){
    	this.service = service;
    }
}

 

  • 테스트 용이
  • 프레임워크에 의존하지 않고 자바 언어로만 구현 가능
  • 불변성 확보
  • 순환 참조 방지
  • 컴파일 시점에 오류 발견!

정리

 

의존관계 주입은 애플리케이션 시작~종료까지 변경할 일이 거의 없음.

대부분은 의존관계 변화하면 안된다.

 

수정자 주입은 set 메서드를 public으로 열어두어야 함 

의도하지 않은 곳에서 호출 가능성 有

 

생성자 주입은 필드에 final 키워드 사용 가능.

불변성 보장

 

생성자 주입은 오류 조기 발견

필수 값 누락 or 순환참조 컴파일 시점에서 잡아줌 

 

 

후기

 

딥하게 이해하고 넘어 가려하니 막히는 부분이 많았던 내용이었다.

그 중에 하나는 set 방식과 필드 주입은 final을 쓸 수 없는데, 생성자 주입만 가능한 이유는 무엇일까? 이다.

final의 특성에 대해 다시 한번 조사하고 상기시켜 본 결과, 기본적으로 final은 객체가 만들어지기 전 즉, 생성자가 

객체를 최종적으로 생성하기 전에 값이 초기화 되어야 한다.

아무 값으로도 초기화 되지 않았는데 해당 변수를 이용한 메서드가 선언되어 있거나 하면 오류가 생긴다.

이 경우가 set 방식이 final을 쓰지 못하는 이유.


그렇다면 field 주입 방식은 왜 final을 쓰지 못할까? 에 대한 해답은?

 

구글  및 관련 강의 검색, 그리고 스스로 코드도 짜보고 내린 결론은

일단 생성자 주입 방식은 생성자를 만드는 시점에 의존 관계로 등록 될 변수의 값과 의존관계가 함께 설정된다.

 

하지만 field 주입 방식은 생성자 호출 즉, 객체를 만들고 나서야 의존 관계 주입이 이루어진다.

객체를 만들기 전, final 변수의 값을 초기화 해주어야 한다는 점은 앞서 set 필드 주입에서 익혔던 개념이다.

그렇기에 "field 주입은 final을 넣으면 안되는 군.." 라는 결론이 나왔다.


마지막으로 의아했던 부분은 field 방식을 선택하면 지나친 의존 어노테이션(@Autowired) 남용으로 인해

SRP(단일 책임 원칙)을 어기게 된다. 라고 하는 정보가 있었다.

 

이 주장의 근거는 "filed 방식을 통해 하나의 클래스 내부에 @Autowired를 너무 많이 쓰면 책임이 집중된다.

그렇기에 생성자 방식을 통해 생성자가 길어지는 현상을 보고 리팩토링을 하여 SRP를 사전에 방지할 수 있다."

라는 내용이었다. 일단 기본적으로 생성자가 길어진다는 말의 의미가 "클래스의 변수가 많아져 난잡해진다"라는 의미라면

 

다음과 같이 요즘 최신 버전 spring boot는 구현하려는 클래스가 bean이며, 생성자 자동 생성(하나 일 때) 및 의존관계 설정을 어노테이션 하나로 끝낼 수 있어서

생성자 주입 방식의 가시적인 문제는 기본적으로 아래와 같이 해결이 가능하다. 그렇기에 생성자 주입 방식이 SRP를 사전에 방지한다는 문구는 현재 시점에 있어서 힘이 실리지 않는 내용.

 

@Controller
@RequiredArgsConstructor
public class Controller{

	private final BasicService basicservice;
        private final HardService hardservice;
    
}

 

이는 가시적인 문제의 해결일 뿐, 근본적으로 지나친 의존 관계를 해결 가능한 것은 아니기 때문에

 

결론적으로 SRP 위반한다는 내용은 지금으로선 이해하기 힘든 정보인 것 같다.

 

 

 

728x90