본문 바로가기

개발/Spring

Field Injection vs Constructor Injection

현 직장에서 의존성주입이 모두 Field Injection으로 되어 있었습니다. 코드 리팩토링을 하는데 동료 중 한분이 Field Injection을 Constructor Injection으로 바꾸는게 좋겠다고 의견을 주었습니다. 근데 저는 그 둘의 차이를 잘 몰라서,,, 한번 알아보았습니다.

Field Injection

필드주입의 예시는 아래와 같습니다.

@Service
public class SampleService {
	
	@Autowired
	private PaymentService paymentService;
	
	public void callPayment() {
		paymentService.callPayment();
	}

}

의존성 주입시 Autowired 어노테이션을 사용하여 표현할 수 있습니다.

 

 

Constructor Injection

생성자 주입은 아래와 같습니다.

@Service
public class SampleService {
	
	private final PaymentService paymentService;
	
	public SampleService(PaymentService paymentService) {
		this.paymentService = paymentService;
	}
	
	public void callPayment() {
		paymentService.callPayment();
	}

}

 

간단한 예제로 보면 생성자 주입이 코드도 더 많이 작성해야 하고 귀찮아 보일 수 있습니다.

하지만 비지니스 로직이 복잡해질수록 생성해야하는 서비스도 많아지고 코드도 복잡해집니다. 개발을 하다가 서로 다른 서비스가 의존성을 가지게 되는 코드를 작성할 수 있는데 이를 순환참조라고 합니다.

생성자 주입의 첫번째 장점은 순환참조를 미리 방지할 수 있다는 점입니다.

순환참조의 극단적인 예시를 한번 코드로 보겠습니다.

@Service
public class PaymentService {
    @Autowired
	private OrderService orderService;
    
	public void callPayment() {
		List<Order> orderList = orderService.getOrderList();
	}

}
@Service
public class OrderService {
	
    @Autowired
	private PaymentService paymentService;
	
	public List<Order> getOrderList() {
		paymentService.callPayment();
	}

}

OrderService에서 PaymentService를 호출하고 PaymentService에서 OrderService를 호출하는 것입니다. 예시를 필드주입으로 작성하였는데 이유는 필드주입으로 순환참조가 생성될 경우 어플리케이션 구동도 잘되고 문제가 없어보입니다. 그러나 실제로 해당 서비스를 호출하게 되면 StackOverflowError에러가 발생하면서 어플리케이션이 중지될 것입니다. 

반면 생성자주입으로 코드를 작성한 경우 어플리케이션 구동 시점에서 에러가 발생하면서 어디에 문제가 있는지 알려줍니다. 

 

생성자 주입의 두번째 장점은 final 예약어를 사용하여 어플리케이션이 재구동되기 전까지 객체를 Immutable한 상태로 만들 수 있습니다. thread safe한 개발이 가능한 것이죠. 

 

그럼 특정 서비스에 의존성이 많이 필요한 경우에는 일일이 생성자에 넣어줘야하는데 너무 귀찮습니다... 그래서 저는 lombok에서 제공하는 @RequiredArgsConstructor 어노테이션을 사용합니다.

 

 

 

'개발 > Spring' 카테고리의 다른 글

RestTemplate와 WebClient 비교  (0) 2022.02.22
SIGTERM이란 ?  (0) 2021.03.18