빙응의 공부 블로그

[Spring]스프링 핵심 원리 - 의존 관계 주입2 본문

Spring/인프런_개념

[Spring]스프링 핵심 원리 - 의존 관계 주입2

빙응이 2023. 12. 28. 15:48

📝롬복과 최신 트랜드

막상 개발을 해보면, 대부분이 다 불변이고, 그래서 다음과 같이 필드에 final 키워드를 사용한다. 

그런데 생성자도 만들고, 주입받는 값을 대입하는 코드도 만들어야 한다.

스프링은  Lombok을 이용하여 간결하게 코딩이 가능하다. 

 

 

생성자 자동 생성

기본코드

@Component
public class OrderServiceImpl implements OrderService {
 private final MemberRepository memberRepository;
 private final DiscountPolicy discountPolicy;
 
 public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy
discountPolicy) {
 	this.memberRepository = memberRepository;
 	this.discountPolicy = discountPolicy;
 }
}

 

롬복 사용 코드 

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

 private final MemberRepository memberRepository;
 private final DiscountPolicy discountPolicy;
 
}

@RequiredArgsConstructor 를 이용하면 생성자를 자동 생성해준다.

 

getter, setter 자동생성
@Data
public class HelloLombok {
  private String name;
  private int age;
}
  • @Data : 자동으로 getter, setter을 만들어준다.
    • @getter
    • @setter
  • @toString 

 

 

📝조회 빈이 2개 이상인 문제 

@Autowired는 타입으로 조회하기 때문에 ac.getBean(DiscountPolicy.class)와 유사하다!

 

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

@Component
public class RateDiscountPolicy implements DiscountPolicy {}

만약 이 상태에서 의존관계 자동 주입을 실행하면 

NoUniqueBeanDefinitionException 오류가 발생한다. 

 

문제 해결법

  • 하위 타입을 지정 -> DIP 위반으로 유연성이 떨어진다. 
  • @Autowired 필드 명 매칭 
  • @Quilifier
  • @Primary

 

@Autowired 필드 명 매칭 

@Autowired는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 추가 매칭한다.

@Autowired
private DiscountPolicy discountPolicy

@Autowired
private DiscountPolicy rateDiscountPolicy

아래 코드로 바꾸면 문제가 사라진다. 

 

@Qualifier 사용
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {}

@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
 @Qualifier("mainDiscountPolicy") DiscountPolicy
discountPolicy) {
 this.memberRepository = memberRepository;
 this.discountPolicy = discountPolicy;
}

@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy") 
DiscountPolicy discountPolicy) {
 this.discountPolicy = discountPolicy;
}

@Qualifier으로 이름을 지정해 줄 수 있다. 

 

 

@Primary 사용 

@Primary는 우선순위를 정하는 방법이다. 

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

 

정리
  • @Autowired 매칭 정리
    • 타입 매칭으로 매칭 결과가 2개 이상일 때 필드 명, 파라미터 명으로 빈 이름 매칭한다. 
  • @Qualifier 사용
    • @Qualifier끼리 매칭
    • 빈 이름으로 매칭한다.
    • 없을 시 NoSuchBeanDefinitionException 예외 발생
  • @Primary 사용
    • 우선순위를 이용한 매칭 

뭘 사용해야하는가?

  • @Primary의 경우
    • 주로 기본적으로 사용할 빈을 선택할 때 유리 
    • @Qualifier보다 코드가 간결하다. 
    • 여러 후보 중 한가지만 항상 선택되므로 유연성이 떨어짐
  • @Qualifier의 경우
    • 특정 상황에서 특정 빈을 사용하는 유연성이 좋음
    • 여러 빈 중 명시적으로 사용 가능하다. 
    • 코드가 복잡해 질 수 있다. 반드시 명시적으로 사용

 

📝자동과 수동의 올바른 실무 운영 기준 

편리한 자동 기능을 기본으로 사용하자 
  • 스프링이 나오고 시간이 갈 수록 점점 자동을 선호하는 추세이다. 스프링은 다양한 계층에 맞추어 일반적인 애플리케이션 로직을 자동으로 스캔할 수 있도록 지원한다. 
  • 설정 정보를 기반으로 애플리케이션을 구성하는 부분과 실제 동작하는 부분을 명확하게 나누는 것이 이상적이지만, 개발자 입장에서 스프링 빈을 하나 등록할 때 @Component 만 넣어주면 끝나는 일을 일일이 AppConfig 처럼 만드는 것은 번거롭다
  • 그리고 결정적으로 자동 빈 등록을 사용해도 OCP, DIP를 지킬 수 있다.

 

로직에 따른 사용
  • 업무 로직 빈 : 자동을 사용하는 것이 좋다.
    • 웹을 지원하는 컨트롤러
    • 핵심 비즈니스 로직이 있는 서비스
    • 데이터 계층의 로직을 처리하는 리포지토리 
  • 기술 지원 빈 : 수동으로 사용하는 것이 좋다. 
    • 기술적인 문제나 공통 관심사(AOP) 처리 
    • 데이터 베이스 연결이나, 공통 로그 처리 등 업무 지원에 필요한 하부 기술이나 공통 기술

 

  • 업무 로직은 숫자가 매우 많고, 한번 개발해야 하면 컨트롤러, 서비스, 리포지토리 처럼 어느정도 유사한 패턴이기 때문에 자동 기능을 적극적으로 사용하는 것이 좋다.
  • 기술 로직은 업무 로직과 비교하여 수가 매우 적고, 보통 애플리케이션 전반에 걸쳐서 광범위한 영향을 미치기 때문에 가급적으로 수동을 사용하는 것이 좋다.

 

 

비즈니스 로직 중에서 다형성을 적극 활용할 대 

특정 패키지를 같이 묶어두는게 좋다. 

@Configuration
public class DiscountPolicyConfig {
 
 @Bean
 public DiscountPolicy rateDiscountPolicy() {
 	return new RateDiscountPolicy();
 }
 @Bean
 public DiscountPolicy fixDiscountPolicy() {
 	return new FixDiscountPolicy();
 }
}

설정 정보만 보고 이해가 바로 되지 않는가? 이처럼 특별한 빈들은 따로 모아서 유지하자.