당니의 개발자 스토리

필터 본문

스프링/스프링 핵심 원리 - 기본편

필터

clainy 2024. 1. 24. 17:27

필터

이번 시간에는 필터에 대해서 알아보겠습니다.

이름 그대로 includeFiltersexcludeFilters가 있고요. 컴포넌트 스캔에 추가할 대상, 컴포넌트 스캔에서 제외할 대상을 각각 지정할 수가 있습니다.


빠르게 그냥 예제로 해볼게요.

scan에다가 패키지를 만들어볼게요. filter라는 패키지를 만들겠습니다.

그리고 애노테이션을 만들 거예요. @Annotation을 고르구요.

MyIncludeComponent 라는 애노테이션을 임의로 만드는 거에요. 애노테이션 관련해서는 공부를 하셔야 되는데,

@Component에 들어가면, @Target 이라고 있습니다.

이거 세 개만 붙여넣기 해줍니다.

이 중에서 @Target이 중요한데,

이 애노테이션이 TYPE에 붙냐, FIELD에 붙냐 이런건데요, TYPE이라고 하면, 클래스 레벨에 붙는 거겠죠.

이렇게 하면 끝입니다. 결국 '@MyIncludeComponent가 붙은 거는 컴포넌트 스캔에 추가할 거야.' 라는 걸로 이해하면 되고, 또 하나 더 만들건데,

복붙해서 만들겠습니다.

이렇게 해서, 어노테이션을 2개 만든 거에요. @MyExcludeComponent가 붙은 거는 컴포넌트 스캔에서 제외할 겁니다.

그 다음에, filter 패키지 안에다가 클래스를 두 개 만들게요.

하나는 BeanA이고, @MyIncludeComponent 를 붙여줍니다. 그리고 이걸 복붙해서

@MyExcludeComponent로 바꾸고, BeanB를 만들겠습니다. 그럼 BeanB는 컴포넌트 스캔에서 제외하겠죠.

이렇게 해놓고, filter 안에다가 테스트를 하나 만들어볼게요.

ComponentFilterAppConfigTest를 만들겠습니다.

그 다음,

테스트할 메서드를 만들고, 스프링 컨테이너를 만듭니다.

그 전에, Configuration 클래스를 만들어야겠죠.

static classComponentFilterAppConfig를 만들었습니다.

그 다음, 이게 설정 파일임을 알려주기 위해서, @Configuration 을 넣고, @ComponentScan을 넣어서,

이게 잘 되는지 테스트해야 합니다.

따라서, includeFilters 해서, 컴포넌트 스캔 대상추가로 지정합니다. 그리고 필터 타입을 ANNOTATION으로 하면,

애노테이션과 관련된 필터를 만드는 거에요. 그러면서,

MyIncludeComponent.class를 넣어주고, @Component static import 해줍니다.

그리고 나서, 이번에는 excludeFilters를 넣어줍니다. 그래서 컴포넌트 스캔 대상에서 제외해주는 거죠.

이렇게 하면, 나만의 컴포넌트를 스캔할 수 있는 기능이 만들어집니다.

이렇게 해서, 스프링 컨테이너에다가 설정 정보 클래스를 지정해주고요.

이제 잘 되는지 해보면 되겠죠. 우리가 원하는대로, Filter로 걸러졌는지 봅시다. getBean 해서 꺼내봅시다.

Bean으로 올라온 것들 중 BeanA는 있어야 되고, BeanB는 없어야 합니다.

일단 이렇게 하고 돌려보겠습니다. 잘 돌아갑니다.

그럼 이제 beanB를 조회하면 어떻게 될까요?

beanB를 조회하는 순간, Exception이 터져야겠죠.

No bean named 라고 나오죠. 우리가 beanB를 excludeFilter를 써서, @MyExcludeComponent이 붙은 것들은 컴포넌트 스캔에서 제외하겠다. 라고 한 거기 때문에 그러한 빈이 없다라고 나오는 겁니다.

테스트를 완성하기 위해서, junitAssertions를 불러오겠습니다. 왜냐하면 assertThrows를 써야하기 때문이죠.

이렇게 하고, Asserions도 static import 하면,

이렇게 줄여집니다. 이제 돌려봅시다.

테스트를 성공했습니다. 첫 번째 건 NULL이면 안 되죠. 같이 조회 되어야하고, 두 번째거는 NoSuchBeanDefinitionException이 나와야합니다.


이렇게 해서 코드까지 확인 끝났고 정리해보겠습니다.

includeFilters MyIncludeComponent 애노테이션을 추가해서 BeanA가 스프링 빈에 등록이 됐지만, excludeFiltersMyExcludeComponent 애노테이션을 추가해서 BeanB는 스프링 빈에 등록되지 않았습니다.

그리고 이 필터 타입의 옵션이 5가지가 있어요.


필터 옵션에 대해서 알아볼게요.

ANNOTATION이 기본값이에요. 애노테이션을 인식해서 동작하는 거구요.

기본 값이어서 이 부분은 사실 생략해도 됩니다.

그래도 잘 동작합니다.

그 다음에 또 뭐가 있냐면, ASSIGNABLE_TYPE 이라는 게 있어요. 얘는 지정한 타입자식 타입을 인식해서 동작합니다. org.example.SomeClass 이렇게 클래스를 그냥 직접 지정해 줄 수 있는 거에요.

그리고 ASPECTJ는 AspectJ 패턴으로 그냥 바로 찾아오는 거에요.

그리고 REGEX 하면, 정규표현식도 사용할 수가 있구요.

그 다음 CUSTOM은 이 TypeFilter 라는 인터페이스를 구현해가지고 직접 프로그래밍으로 조건을 만들 수 있습니다.

예를 들어서, BeanA를 빼고 싶어요.

그럼 FilterType에다가 ASSIGNABLE_TYPE 으로 지정해주시구요. 클래스를 직접 지정해서 'BeanA 뺴!' 하는 겁니다.

이거는 굳이 코드를 해보진 않을게요. 사실 잘 사용하는 일이 별로 없어 가지고, 가끔 ASSIGNABLE_TYPE 정도 사용하고 annotation이 이미 다 구비가 되어있잖아요. component 이런 게. 그래서 요즘엔 includeFilters, excludeFilters를 사용할 일이 크게 많이 없더라구요.

그래서 사실 @Component면 충분하기 때문에 includeFilters를 사용할 일은 거의 없어요. excludeFilters 같은 경우에는 간혹 사용할 때가 있어요. 우리도 @Configuration 뺀다고 사용해봤었죠. 특히 최근 스프링 부트는 컴포넌트 스캔을 기본으로 제공해요. @SpringBootApplication에서 알 수 있죠.

그래서 개인적으로는 옵션을 변경하면서 사용하기 보다는 스프링이 제공하는 기본 설정에 최대한 맞추어서 사용하는 걸 권장을 하고 선호하는 편입니다.


이렇게 해서 필터 옵션까지 알아봤구요.

다음 시간에는 스프링 빈이 중복 등록했을 때 어떻게 될까? 충돌이 됐을 때 어떻게 될까?

스프링 빈을 수동 등록한 거와 자동 등록한 게 충돌이 되면 어떻게 하지? 이런 거에 대해서 알아보겠습니다.