Spring - DI (의존성 주입)

hisungmi·2024년 12월 19일

Java-Spring

목록 보기
3/8
post-thumbnail

DI - 의존성 주입

의존성(Dependency)

💡의존성 : 한 객체의 코드에서 다른객체를 생성하거나 다른 객체의 메서드를 호출할 때,
  의존성이 발생한다고 함
  

결합도(Coupling)

💡의존성의 정도
  • 높으면 강한 결합 (Tight) : new 연산자를 사용하여 객체를 생성할 때
  • 낮으면 느슨한 결합 (Loose) : 인터페이스와 같이 일반화 된 구성 요소에 의존하고 있을 때

👾 강한 결합

  • 아이폰에서 갤럭시로 휴대폰을 교체하는 경우
  • 갤럭시에 대한 멤버 변수를 생성... 등 많은 코드가 변경됨

👾 느슨한 결합

  • 인터페이스 클래스를 이용해 추상화하여 클래스간 의존성 최소화
  • 요구 사항 변경에 유연한 대처 가능

의존성 주입(Dependency Injection)

💡의존성 주입은 자신이 사용할 객체에 대한 선택과 생성 제어권을 외부로 넘기고 
  자신은 수동적으로 주입받은 객체를 사용한다는 것

➡️ 즉, 스프링 컨테이너의 IoC는 주로 의존성 주입에 초점이 맞춰져 있다.

장점

  • 클래스들 간의 강한 결합을 느슨한 결합으로 ➡️ 유연한 대처
  • 테스트가 자유로워짐 ➡️ 결합도가 낮기 때문

주입 방법

😁 생성자 주입
생성자에 @Autowired를 하면 스프링 컨테이너에 @Component로 등록된 빈에서 생성자에 필요한 빈을 주입함


@Component
public class AirpodsController {
	private final AirpodsService airpodsService;
	public AirpodsController(AirpodsService airpodsService) {
		this.airpodsService = airpodsService;
	}
}

특징

  1. 생성자 호출 시점에 1번만 호출되는 것을 보장 이후, 값을 변경하지 못하게 막을 수 있음
  2. 불변과 필수 의존 관계에 사용
    • 불변 : 생성자를 통해서만 의존 관계가 주입되고, 외부에서 수정할 수 없다.
    • 필수 : 무조건 값이 있어야 한다.
  3. 생성자가 1개만 존재하는 경우 @Autowired를 생략해도 자동 주입
  4. 주입 받을 필드를 final로 선언할 수 있음
    • final로 선언된 레퍼런스 타입의 변수는 반드시 선언과 동시에 초기화가 이뤄져야함
    • final로 선언된 변수는 객체가 불변하도록 할 수 있다는 장점, 코드의 신뢰성, 유지보수성, 가독성 향상 가능

😁 수정자(setter) 주입

필드 값을 변경하는 수정자 메서드를 통해 의존 관계를 주입하는 방법


@Component
public class AirpodsController {
	private AirpodsService airpodsService;
	@Autowired
	public void setAirpodsService(AirpodsService airpodsService) {
		this.airpodsService = airpodsService;
	}	
}

특징

  1. 선택과 변경 가능성이 있는 의존 관계에 사용
    • 선택 : 스프링 빈으로 등록되지 않은 인스턴스 또한 주입 가능
    • 변경 : 변경 가능성 있는 의존 관계 사용시, 중간에 setter메서드를 호출하여 의존 관계 변경
  2. 수정자 메서드를 이용해서 의존 관계 주입
  3. @Autowired를 입력하지 않으면 실행 안됨

단점

  • Set 메서드의 경우 public으로 구현하기 때문에 관계를 주입 받는 객체의 변형 가능성이 있다.
    즉, 객체가 변경 될 필요성이 있을 때 사용이 권장된다.

자바빈 프로퍼티

💡Java에서 필드의 값을 직접 변경하지 않고 set, get메서드를 통해
  값을 읽어오거나 수정하는 규칙 ➡️ (수정자 메서드 방식을 사용하는 방법)
  

😁 필드 주입
변수 선언부에 @Autowired를 붙여 주입하는 방법


@Component
public class AirpodsController {
	@Autowired
	private AirpodsService airpodsService;
}
  • 의존성을 주입하기 쉬움, 참조 관계를 확인하기 어려움

단점

  • Spring 같은 DI를 지원하는 프레임워크가 있어야만 사용 가능
  • 필드 주입으로 의존성 주입 시 final 키워드를 통한 선언 불가능, 객체가 변하기 쉬워짐

😁 생성자 주입 방식을 사용하자!

장점

1. 객체 불변성을 확보 할 수 있다. (final 키워드 사용 가능)

  • 객체의 생성자는 객체 생성 시 1회만 호출되는게 보장
    즉, 주입 받은 객체가 불변 객체로 설계할 수 있으며, 의존성 주입을 누락하는 것을 방지할 수 있음

2. 애플리케이션 구동 시점에 순환 참조 에러 를 알려줌.

  • 생성자 주입은 객체의 생성과 의존 관계 주입이 동시에 실행되지만, @Autowired는 모든 객체의 생성이 완료된 후에 의존 관계 주입이 처리되기에 호출이 되고 나서야 순환 이슈를 확인할 수 있다.
profile
난 성미다.

0개의 댓글