Field Injection 왜 권장하지 않을까?

 

우테코 체스 미션에 스프링을 도입했다. 어노테이션을 통한 의존성 주입은 신세계 였다. InteliJ에서 노란줄을 띄웠음에도  필드 주입을 주로 사용했다. (간결해..!) 리뷰어 분께서 필드 주입에 관해서 피드백을 주셨다. 이번 포스팅은 피드백 주신 대로 필드 주입이 무엇인지, 왜 권장하지 않는지, 대안은 무엇인지 학습해 볼 것이다.

 

 

필드 주입 이란

 

  • @Autowired를 필드에 직접 사용하는 경우를 필드 주입이라고 한다.
@AutoWired
private ChessService chessService;

 

왜 필드 주입을 권장하지 않는가?

 

순환참조

  • A가 B를 참조하고, 다시 B가 A를 참조하는 경우를 말한다.
class A {
    @Autowired
    private B b;
    
    public void do() {
    	b.do();
    }
}

class B {
    @Autowired
    private A a;
    
    public void do() {
    	a.do();
    }
}

 

  • 필드 주입의 경우 어플리케이션 빌드 시 문제가 발생하지 않음
    • 빈을 먼저 생성하기 때문에
  • 실제 코드가 동작할 때 StackOverFlowError: null 발생
  • 서로가 서로의 객체를 참조하여 메소드를 실행할 경우 무한루프 발생

 

 

class A {
    private B b;
    
    @Autowired
    public A(B b) {
        this.b = b;
    }
}

class B {
    private A a;
    
    @Autowired
    public B(A a) {
        this.a = a;
    }
}

 

  • 생성자 주입의 경우 어플리케이션 빌드 시점에서 예외 발생 
    • BeanCurrentlyCreationException
  • 주입하려는 빈을 먼저 찾고, 주입하여 빈을 생성
    • A를 만들려면 B를 찾아야하고, B를 만들려면 A를 찾아야 하는 상황

 

 

테스트의 용이성

  • DI 프레임 워크의 핵심 아이디어 중 하나는 관리되는 클래스가 DI 컨테이너에 의존하지 않아야 한다.
  • DI 프레임 워크를 사용하지 않고도 독립적으로 인스턴스화 할 수 있어야 한다.
@AutoWired
private ChessService chessService;

 

  • 필드 주입의 경우 SpringChessController를 인스턴스화 하기 위해서는 스프링 프레임워크가 필요하다. 
  • 스프링 프레임워크에서 chessService를 주입시켜 줘야 하기 때문이다.

 

private final ChessService chessService;

@Autowired
public SpringChessController(ChessService chessService) {
	this.chessService = chessService;
}

 

  • 생성자 주입의 경우 테스트 시 ChesssService 구현체를 넘겨주어 인스턴스화가 가능하다.

 

불변성

  • 생성자 주입에서는 final 키워드 사용이 가능하다.
  • 혹시 모를 Bean이 변경되는 상황에 대해 안전하다.
private final ChessService chessService;

@Autowired
public SpringChessController(ChessService chessService) {
	this.chessService = chessService;
}

 

 

필드 주입의 대안

 

  • 필드 주입의 대안으로는 생성자 주입과 세터 주입이 있다.
의존성 명시

의존 객체 중 필수는 Constructor Injection을 옵션인 경우는 Setter Injection을 활용할 수 있다.

 

  • 세터 주입은 아래와 같이 사용이 가능하다.

 

class A {
	private B b;
    
    @Autowired
    public setB(B b) {
        this.b = b;
    }
}

'study' 카테고리의 다른 글

Spring 동작원리  (2) 2021.04.30
Spring @Valid, @Validated Annotation  (2) 2021.04.22
Spring이란?  (0) 2021.04.20
[Spring]Request Mapping  (2) 2021.04.13
DAO와 Repository  (7) 2021.04.08

댓글



Designed by JB FACTORY