Dependency (의존) ?

A가 B에 의존하고 있는 상태일 때, B에 변화가 일어나면 그 변화가 A에도 영향을 미치는 것

 

class Chef {
    private Recipe recipe = new Recipe();

    public Chef() {
       this.recipe.cook();
    }
}

 

흔히 드는 예시 중 하나

요리사는 레시피에 의존

따라서 레시피가 바뀌면 요리사의 행위도 변화

 

Chef 객체는 Recipe객체를 생성하고, 그 객체가 가지고 있는 cook이라는 메소드를 활용

만약 Recipe가 하나가 아니라 여러개가 존재하고, Recipe를 추가, 수정, 삭제하고 싶다면 해당하는 객체에 대한 코드를 추가, 수정, 삭제 필요

 

>> 코드 결합도가 높아지게 되어 코드 재활용성 등 문제 발생

의존성 주입을 사용하는 이유

 

Dependency Injection 사용

public class Recipe {...}
public class Pizza extends Recipe{...}
public class Chicken extends Recipe {...}

class Chef {
    private Recipe recipe = new Recipe();

    public Chef(Recipe recipe) {
       this.recipe = recipe;
    }
    
    public startCook(){
    	this.recipe.cook();
    }
}

Chef 객체에 Recipe라는 객체를 주입해서 사용

Pizza, Chicken 등 다른 레시피를 요리하고 싶다면 해당 요리의 객체를 Chef객체에 넘겨주어 생성

하나의 코드를 계속해서 재사용 가능

 

 

DI의 장점

1. 코드의 재활용성 증가

2. 객체 사이의 의존성/종속성 감소

3. 가독성 증대

4. Test 용이

 

 

 

Spirng에서의 DI

Spring은 DI를 편하게 사용하는 방법 3가지 제공

 

1. 생성자 주입

Contstructor Injection

@Service
public class UserServiceImpl implements UserService{
    private UserRepository userRepository;
    private UserServiceImpl userService;

    @Autowired
    public UserServiceImpl(UserRepository userRepository, UserService userService){
        this.userRepository = userRepository;
        this.userServicer = userService;
    }
}

생성자 주입은 생성자 호출 시점에 1번 호출 되는것이 보장

주입받는 객체의 변화가 없거나 반드시 객체의 주입이 필요한 경우에 강제하기 위해 사용 가능

 

** Spring에서는 생성자가 1개만 있을 경우 @Autowired는 생략 가능

 

 

2. 수정자 주입

Setter Injection

Setter를 사용해서 의존 관계를 주입하는 방법

주입 객체가 변할 수 있는 경우에 사용

@Service
public class UserServiceImpl implements UserService{
    private UserRepository userRepository;
    private UserServiceImpl userService;

    @Autowired
    public void setUserRepository(UserRepository userRepository){
        this.userRepository = userRepository;
    }
    
    @Autowired
    public void setmUserService(UserService userService){
        this.userService = userService;
    }
}

@Autowired로 주입 대상이 없는 경우에는 오류 발생 >> Bean에 존재하지 않는 경우

 

 

3. 필드 주입

Feild Injection

필드에 의존 관계를 주입하는 방법

@Service
public class UserServiceImpl implements UserService{
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private UserServiceImpl userService;
    
}

코드가 간결하기 때문에 과거에 많이 사용되던 방법 

But 외부에서 변경이 불가능 >> Test코드에서 Mock데이터를 사용하여 주입 불가

 

Spring과 같은 DI프레임워크가 존재해야만 사용 가능

 

 

 

생성자 주입을 권장하는 이유

  • 객체의 불변성 확보
  • Test코드의 작성
  • final키워드 작성 및 Lombok 결합

DI를 위한 3가지 방법 중 생성자 주입만이 객체 생성과 동시에 의존성 주입 >> final 변수 할당 가능 !!

나머지 방법은 객체를 우선 생성 => 의존성 주입 함수 호출 

순서로 수행되기 때문에 finla 변수 할당 불가능

 

  • 순환참조에러 방지

클라이언트 구동 시, Bean에 등록하기 위해 객체를 생성하는데, 이때 순환참조 발견 시 바로 에러 호출

만약 수정자 주입을 사용한다면 객체 생성 후, 객체에 의존성을 주입하는 순간에 에러 호출되기 때문에 생성만 한 상태에서는 코드가 잘못되었는지 발견하기 힘듬

 

 

'끄적 > BE' 카테고리의 다른 글

MVC1 MVC2  (0) 2023.01.05
Inversion of Control (제어 반전)  (0) 2023.01.03
Persistence Context (영속성 컨텍스트)  (0) 2023.01.01
Spring MVC  (0) 2022.12.29
JPA, Spring Data Jpa  (0) 2022.12.28

+ Recent posts