[기본기] 7-8. Map, List활용하여 빈 다 끌어오기, 정리

khyojun·2022년 10월 7일
1
post-thumbnail

본 게시글은 김영한님의 스프링 핵심 원리 기본편을 정리한 글입니다.


📌 조회할 빈들을 다 조회하고 싶을면 Map, List를 활용하자.

기본적으로 스프링에서 Map, List를(여기에 Set도 활용할 수 있다.) 활용하면 자동적으로 스프링에서는 해당하는 타입의 Bean들을 다 끌어온다고 한다. 한 번 알아보자.

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 fixDiscountPolicy = discountService.discount(member, 12000, "fixDiscountPolicy");

        Assertions.assertThat(discountService).isInstanceOf(DiscountService.class);
        Assertions.assertThat(fixDiscountPolicy).isEqualTo(1000);

    }

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

        public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policyList) {
            this.policyMap = policyMap;
            this.policyList = policyList;
            System.out.println("policyMap = " + policyMap);
            System.out.println("policyList = " + policyList);
        }
        
        public int discount(Member member, int price, String discountCode){
            DiscountPolicy discountService = policyMap.get(discountCode);
            System.out.println("discountCode = " + discountCode);
            System.out.println("discountService = " + discountService);

            return discountService.discount(member, price);
        }
    }
}

이렇게 할 경우 자동적으로 Map, List에 해당하는 타입에 맞는 빈들을 찾아서 다~~ 주입을 시켜줬다는 것을 알 수 있다.
테스트로는 그 중 하나의 할인정책을 들고와서 잘 동작하는지 확인하는 코드이다. 이게 그렇다고 Map, List뿐만이 아닌 Set형식도 같이 활용을 할 수 있다고 한다. 여기서 또한 다른 부분은 위에서 스프링 컨테이너를 생성할때 new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);를 보면 한 가지가 아닌 여러가지 설정 정보도 넘길 수 있다는 것을 알 수 있다. 그래서 @ComponentScan으로써 빈 등록이 되었던 fixDiscountPolicy, rateDiscountPolicy가 자동적으로 Map, List에 들어가게 된다. List는 해당 타입으로 조회한 모든 빈들을 다 주입시키고 Map은 key에 스프링 빈 이름을 넣어주고 그것에 대한 value로 해당하는 타입을 조회한 모든 스프링 빈들을 주입시킨다.

📌 정리

자동 vs 수동

우리가 이때까지 자동으로 주입하는 방법과 수동으로 주입하는 방법을 보면서 어떻게 보면 "흠... 당연히 자동으로 주입하는 것이 좋지 않을까?" 하는 생각이 많이 들게 된다. 그러면 실제로는 뭘 더 많이 쓸까?

시간이 지나면 지날수록 이제 스프링은 자동을 선호하는 추세라고 한다. 뭐 어떻게 보면 이제 SpringBoot에서는 @ComponentScan이 기본적으로 들어있는 것 보면 자동이 좋다고 생각이 든다.

그래서 강의에서도 언급하신 내용이 다음과 같다.

개발자 입장에서 스프링 빈을 하나 등록 때 @Component만 넣어주면 끝나는 일을 하나 하나씩 수동적으로 @Bean으로 등록을 하고 하면 되게 번거로운 방식이다. 또 관리할 빈이 많아서 설정 정보가 너무 커진다면 관리하는 것 자체만으로 되게 부담스러운 일이다. 그리고 결정적으로 자동 빈 등록을 사용해도 OCP, DIP를 지킬 수 있다.

그치만! 수동을 써야 할 때도 있다.

물론 자동으로 하는게 좋긴 하다. 편하기도 하고 좋은 객체지향 설계방식도 유지해주기도 하고 하지만! 관리를 해야할 때는 수동을 사용해야할 때도 있다고 한다.

업무 로직 빈 vs 기술 지원 빈

애플리케이션은 크게 업무 로직과 기술 지원 로직으로 나눌 수 있다고 한다.

  • 업무 로직 빈 : 웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 리포지토리등이 모두 업무 로직이다. 보통 비즈니스 요구사항을 개발할 때 추가되거나 변경이 된다.
  • 기술 지원 빈 : 기술적인 문제나 공통 관심사를 처리할 때 주로 사용이 된다. 데이터베이스 연결이나, 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술들이다.

어찌 보면 업무 로직 빈의 갯수는 상당히 많을 것이다. 그리고 그에 비하면 기술 지원 빈의 경우에는 갯수가 매우 적고 애플리케이션 전반에 걸쳐서 광범위하게 영향을 미친다고 한다.

그렇다면 수동 빈은 어느 것에 쓰는 것이 좋을까?

업무 로직 빈의 갯수는 많은 것 부터 뭔가 자동을 써야하는 느낌이 강할 거 같은데 업무 로직 빈은 실제로 되게 비슷한 패턴을 많이 사용을 한다고 한다. 개발을 하게 될 경우 서비스, 리포지토리, 컨트롤러 등의 패턴이 유사한 것이 많아 자동 기능을 적극적으로 사용하는 것이 좋다고 한다. 왜냐하면 보통 문제들이 일어나도 어디에서 일어나는지 명확하게 파악하기 쉽기 때문이다.

그렇다면 기술 지원 빈에서는 수동으로 등록하는 방식을 사용한다는 말인데 이유로는 명확하게 문제를 파악하기가 어렵기 때문이다. 실제로 개발하다가 문제가 일어나면 기술 지원 로직이 잘 적용이 되고 있는지 안 되는지 파악하기가 생각보다 되게 힘들다고 한다. 그래서 명확하게 우리가 문제를 파악하기 위하여서 수동 빈 등록을 사용한다고 한다.

그니까 수동 빈 등록을 함으로써 문제를 명확하게 확인하기 위함! 이라는 느낌이다.

한 번 예시를 봅시다.

자동 등록

@Component
@Qualifier("mainDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy


@Component
@Qualifier("rateDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy

수동 등록

@Configuration
public class AppConfig{
    @Bean
    public DiscountPolicy fixDiscountPolicy(){
        return new FixDiscountPolicy();
    }

    @Bean
    public DiscountPolicy rateDiscountPolicy(){
    	return new RateDiscountPolicy();
    }

위 자동 코드와 수동 등록 코드들을 보게 되면 어찌보면 문제가 생겼을때 바로 확인하는 것은 수동 등록이 훨씬 편할 것이다. 그도 그럴 것이 자동등록은 코드를 같이 적어놓긴 했지만 어찌보면 다른 파일이기에 계속 다른곳으로 가면서 확인을 또 해줘야한다. 이게 파일이 뭐 한 두개면 괜찮지만 정말 많아진다면.... ^^; 상당히 곤란할 거 같다. 그래서 내가 직접 기술 지원 객체를 스프링 빈으로 등록을 하는 경우가 생긴다면 꼭 수동으로 등록하여서 명확하게 드러내는 것이 중요하다는 것을 잘 인지하고 가야겠다. 무조건 자동 등록으로만 빈을 남발하지는 않아야겠다.

참고: 스프링과 스프링 부트가 자동으로 등록하는 수 많은 빈들을 얘기하는 것은 아니다. 이런 부분들은 스프링 자체를 잘 이해하고 스프링의 의도대로 잘 사용하는 것이 중요하다. 스프링 부트의 경우 Datasource같은 데이터베이스 연결에 사용하는 기술 지원 로직까지 내부에서 자동으로 등록을 하는데, 이런 부분들은 메뉴얼을 잘 참고하여 스프링 부트가 의도한 대로 편리하게 사용을 하면 된다.

오늘의 결론

Map, List사용하여 해당하는 타입의 빈을 확인할 수 있다.

자동 빈 등록을 사용을 하되 수동으로 사용할 때도 있다는 것을 기억하자.

출처

  1. 김영한님의 스프링 핵심 원리 기본편(https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8)
profile
코드를 씹고 뜯고 맛보고 즐기는 것을 지향하는 개발자가 되고 싶습니다

0개의 댓글