JAVA/Spring_Core

[Spring] 스프링 기능들, 특히 컴포넌트 스캔 공부하면서

kth990303 2021. 3. 11. 22:54
반응형

당분간 블로그 포스팅은 일기 쓰듯이 작성해볼 생각이다.

이후에 내 블로그를 보면서 내 자신이 

'아 이 시절엔 내가 이런 공부를 했었고, 이 부분에서 어려워했구나. 이 때 이러한 점이 모자랐었구나' 를 느낄 수 있게 포스팅은 짬내서 해보려고 한다.

 



인프런 강좌의 김영한의 '스프링 핵심 원리' 강좌를 수강하면서

배운 내용 정리 및 느낀점을 서술하는 포스팅입니다. 


@Configuration?

AppConfig (스프링 빈 세팅해주는 클래스: DI를 담당하는 클래스) 를 보면

위에 Configuration Annotation이 있는 것을 확인할 수 있다.

 

이 Configuration이 뭐냐 하니, 싱글톤을 Solid 원칙을 유지하면서 보장할 수 있게 해주는 것이다!

@Configuration이 있으면, 위 코드에서 memberService, orderService 를 호출하면서 서로 다른 참조값의 memberRepository가 생성이 되지 않고 하나의 같은 memberRepository가 생성되는 것.

 

1. 싱글톤이 보장되지 않으면, 서로 다른 참조값의 리포지토리를 계속 생성해서 메모리 면에서 큰 문제가 되고,

2. 싱글톤 패턴을 유지하려 하면, solid 원칙이 무너지고 (구현 클래스에 client가 의존하므로 DIP를 위반하고, 따라서 OCP 또한 위반할 확률이 높다고 함) 이런 골칫덩어리가 스프링 프레임워크가 단번에 해결해준다는 점.

 

어떻게 이게 가능한 것일까?

바로 스프링에서 CGLIB 바이트코드 라이브러리를 이용해 AppConfig의 자식 관계 클래스를 새로 생성한다는 점에서 이것이 가능해진다. 


??? CGLIB..? 바이트코드? 이게 뭔소리냐. 알아야할 게 또 생긴건가


아니야, 몰라도 돼.

그냥 스프링 프레임워크가 Solid 객체지향 원칙을 지키면서, 싱글톤의 장점 또한 가져가기 위해 우리에게 제공해준다고 생각하면 된다 하더라. (미래의 나야, 혹시 지금은 CGLIB 라이브러리 막 완벽하게 알고 있니..? 궁금하구나)

 

AppConfig@CGLIB 클래스가 새로 생기면서 Appconfig DI 관계는 전부 가지고 있으면서, 

스프링에서 Appconfig@cglib가 이미 있다면 그걸 리턴해주게 하고, 없다면 appconfig에서 객체를 생성시켜 리턴해주게 한다고 한다.

따라서 싱글톤이 보장되는 것!

 

@ComponentScan?

 

근데 스프링을 하면서 뭔가 불편한 점 못느꼈는가?

아래 코드 (위 사진의 코드와 똑같은 사진입니다)를 보면서 불편해보이는 점이 조금이라도 보인다면 손을 들고 발표해봅시다!

지금은 코드가 간단하니까 못느끼겠지만, 객체 생성할 때마다 스프링에게 @Bean 어노테이션으로 이 객체가 appconfig의 spring bean 객체임을 저장시키는 노가다를 하고있다... (사실 지금은 별로 객체들이 없어서 안불편하지만 ㅎ)

 

노가다를 줄여주는 과정이 바로 @ComponentScan이다 이말이야~

 

짜잔, 새로운 AppConfig 클래스인 AutoAppConfig 클래스를 만들어주고,

@Configuration을 붙임으로써 DI하면서 싱글톤, 객체지향 원칙도 유지하게 해줬는데,

어라? @ComponentScan은 뭐야? Filters? 저건 또 뭐지?

 

컴포넌트 스캔을 붙여주면, 우리가 각 객체에 @Bean을 붙일 필요 없이, 스프링이 인식하고 있는 Bean을 자동으로 DI 해준다. 여기서 의존관계 자동 주입이 필요해진다. 일단 이건 좀 이따 생각해보고, 저 위 코드나 이해해보자.

 

 

excludeFilters: 이 필터링 부분은 DI 하지 말아주세요!

@Configuration.Filter(type=FilterType.ANNOTATION): 이 어노테이션이 붙여져 있는것들 말입니다!

classes=Configuration.class : Configuration 어노테이션이 붙여져있는 클래스들은 DI하지 말아주세요!

 

 

아니, 이게 왜 필요한거야?

왜냐면 필자가 기존 AppConfig 클래스를 지워두지 않은 상태로 새로운 AppConfig 클래스인 AutoAppConfig 클래스를 만들어줬기 때문이다. 따라서 기존 AppConfig 클래스를 스캔하지 않게 하려고 저런 짓거리를 한건데, 실무에선 이렇게 excludefilter할 일이 별로 없다고 한다.

 


근데 AppConfig에서는 클래스 내에 코드가 있어서 DI가 이뤄졌는데, 얘는 ComponentScan 어노테이션만 있고, 클래스 내에 코드가 없는데 어떻게 DI가 이루어진다는거야?


의존관계 자동 주입을 이제 알아볼 것이다. 뭐 간단하다. 아래 어노테이션만 있으면 되니까.

 

@Component? @Autowired?

백문이 불여일견, 백문이 불여일타! 아래 코드를 보자

오... 갑자기 @Component, @Autowired 어노테이션이 생겨났다.

(원랜 없었다 ㅎㅎㅎ... Componentscan을 위해 생겨난 것이다)

 

@Component 어노테이션을 붙여줌으로써, 이 클래스 객체를 사용할 것임을 자동으로 알려준다

자, 예를 들어보자. 현재, 할인 정책 두 가지 중 어떤 것을 실행할지를 고민중이다.

 

1. VIP 멤버들에겐 고정적으로 1000원 할인

2. VIP 멤버들에겐 상품의 1%씩 할인

 

둘 다 VIP라 보기엔 애매한 혜택같은데...

우리는 고심 끝에 2번 정책을 실행하기로 했다.

변경의 용이성을 위해 1번, 2번 정책 모두 구현해놓은 상태이다.

 

그럼 우린 1번 객체는 지금은 사용하지 않을 것이고, 2번 객체를 DI에 사용할 것이므로 스프링에 이렇게 알려준다.


야, 2번 클래스 구현체 사용할거야. 알아둬라~ 할인 서비스 정책 DI할 때 1번 쓰지마라. 2번 써라~


 

그렇게 2번 클래스 위에만 @Component 어노테이션을 붙여주고, 1번 클래스엔 붙여주지 않으면

스프링이 신이 나서 DI할 때 2번 클래스만 DI 해준다는 점.

 

 

그럼 @Autowired는 무엇일까?

 

'AppConfig에서는 클래스 내에 코드가 있어서 DI가 이뤄졌는데, 얘는 ComponentScan 어노테이션만 있고, 클래스 내에 코드가 없는데 어떻게 DI가 이루어진다는거야?'

 

바로 이거의 해결책이다.

 

@Autowired 어노테이션이 의존관계 자동 주입 어노테이션이라 보면 되는데, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 등록해준다. 해당 스프링 빈은 당연히 @Component 어노테이션이 붙여진 빈들만 해당이다.

 

즉, @Component가 붙여진 클래스들은 스프링 빈으로 등록되는 것이고,

@Autowired가 붙여지면 의존관계 자동 주입이 이루어지는 것이다!

 

 


스프링 기능이 진짜 엄청 많구나.

그 전까진 '이걸 왜 붙이지? 일단 인강에서 붙이니까 이용해야지' 라는 느낌이라면, 이제 서서히 느낌이 오는 것 같다.

 

근데 남에게 설명하듯이 작성 안하고 나만 대강 알아보게끔 작성하려 했는데,

나도 지금 내용이 머릿속으로 너무 많이 들어와서 쉽게 알아보게끔 정리하는 과정 중 자연스럽게 남에게도 설명하기에 좋은 포스팅을 해버렸다. (사실 그렇게 남에게 이해하기 쉬운 포스팅은 아닌데도...) 쓰는데 30분이나 걸렸다... 뭐, 다른 블로거들은 훨씬 오래 걸린다지만 말이다.

 

 

어서 좀 더 Spring 공부를 해서 스프링 컨테이너에 대한 충만한 이해상태로

Spring security dependency 공부도 해서 로그인 기능도 구현하고 (현재 crud 기능만 구현)

TDD도 잘 작성하고 

자바 실력도 충만해진 상태로 effective JAVA 볼 베이스도 갖춰놓는게 목표다 하하핳...

반응형