본문 바로가기
Learning-log/Spring & JPA

(스프링 핵심 원리 - 기본편) 7-(7) 애노테이션 직접 만들기, (8) 조회한 빈이 모드 필요할 때, List, Map, (9) 자동, 수동의 올바른 실무 운영 기준

by why제곱 2023. 4. 9.

- 애노테이션 직접 만들기

  • @Qualifier("mainDiscountPolicy") 이렇게 문자를 적으면 컴파일 시 타입 체크가 안됨. 
  • 이런 경우 애노테이션을 직접 만들어서 해결 가능

애노테이션 직접 만들기 위해 class 위와 같이 작성
빈에 등록할 객체를 만드는 클래스에 가서 클래스 이름으로 애노테이션 등록

 

해당 빈을 등록시키는 생성자 부분에 가서 애노테이션 사

  • 애노테이션은 상속이라는 개념이 없음
  • 여러 애노테이션을 모아서 사용하는 기능은 스프링이 지원하는 기능인 것.
  • Autowired도 재정의 가능. 하지만 스프링이 제공하는 기능을 뚜렷한 목적 없이 무분별하게 재정의 하면 유지 보수에 혼란을 줄 수 있으므로 삼가자.

 

- 조회한 빈이 모드 필요할 때, List, Map

  • 예제
    • 할인 서비스 제공 시, 클라이언트가 할인의 종류를 선택할 수 있다고 가정
    • 스프링을 사용하면 전략 패턴 간단히 구현 가능
public class AllBeanTest {

    @Test
    void findAllBean(){
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);

        DiscountService discountService = ac.getBean(DiscountService.class);

        Member member = new Member(1L, "USERA", Grade.VIP);
        int discountPrice = discountService.discount(member, 10000, "rateDiscountPolicy");
        assertThat(discountService).isInstanceOf(DiscountService.class);
        assertThat(discountPrice).isEqualTo(1000);
    }

    static class DiscountService{
        private final Map<String, DiscountPolicy> policyMap;
        private final List<DiscountPolicy> policies;

        @Autowired
        public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) {
            this.policyMap = policyMap;
            this.policies = policies;
            System.out.println("policyMap : "+policyMap);
            System.out.println("policies : "+ policies);
        }

        public int discount(Member member, int price, String discountCode) {
            DiscountPolicy discountPolicy = policyMap.get(discountCode);
            return discountPolicy.discount(member, price);
        }
    }
}

 

- 자동, 수동의 올바른 실무 운영 기준

  • 편리한 자동 기능을 기본으로 사용하기
    • 어떤 경우에 컴포넌트 스캔과 자동 주입을 사용하고 어떤 경우에 수동으로 빈을 등록하고 의존관계도 수동으로 주입해야 할까?
      • 점점 자동 선호 추세
      • 설정 정보를 기반으로 애플리케이션을 구성하는 부분과 실제 동작하는 부분을 명확하게 나누는 것이 이상적
      • 하지만 개발자 입장에서 스프링 빈을 하나 등록할 때 @Component만 넣으면 끝날텐데 하나하나 @Configuration 설정 정보에 가서 @ Bean을 적고 객체 생ㅇ성, 주입할 대상을 일ㅇ리이 적어주는 과정은 번거롭고 설정 정보를 관리하는 것이 부담스러워짐
      • 자동으로 등록해도 OCP, DIP 지키는 것도 가능하니 자동을 점점 선호하는 것
    • 수동은 언제 사용할까?
      • 애플리케이션 = 업무로직 + 기술 지원로직으로 나뉨
      • 업무 로직 빈 : 웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 리포지토리 등이 모두 업무 로직. 이는 비즈니스 요구사항을 개발할 때 추가되거나 변경 됨.
      • 기술 지원 빈 : 기술적인 문제나 공통 관심사(AOP)를 처리할 때 주로 사용됨. 데이터베이스 ㅇ연결이나 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술들
      • 업무로직은 매우 많고 한번 개발해야 하면 컨트롤러, 서비스, 리포지토리처럼 유사한 패턴이 존재하므로 이런 경우 자동기능 적극 사용 괜찮음. 문제가 발생해도 문제 명확하게 파악하기 쉬운 편
      • 기술 지원로직은 업무 로직에 비해 수가 적고, 문제 발생 시 애플리케이션 전반에 광범위하게 영향을 미치므로 가급적 수동 빈 등록을 하여 명확히 밖으로 드러내는 것이 좋음.
      • 비즈니스 로직 중 다형성 적극 사용 시! 
        • 의존관계 자동 주입 시, 조회한 빈이 모두 필요할 때 List, Map 다시 보기
        • 다형성을 적극 활용할 때 각 빈들의 이름이 무엇일지, 코드만 보고 한번에 쉽게 파악하기 어려움. 특히 다른 개발자가 짠 코드를 파악하려면 더욱 어려울 것. 따라서 이런 경우 수동 빈으로 등록하거나 자동으로 한다면 특정 패키지에 같이 묶어두는 것이 좋음. 
      • 스프링과 스프링 부트가 자동으로 등록하는 빈들은 예외.
        • 스프링의 의도대로 사용하는 것이 좋음. ex. DataSource
        •