저번 시간에 IoC,DI,Spring Container,Spring Bean에 대해 배웠었다. 이번 시간에는 3가지 어노테이션인
@Component
@ComponentScan
@Autowired에 대해 저번 시간에 배웠던 개념을 사용하여 설명해보도록 하자.
저번시간에 배웠던 개념들은 IoC,DI,Container,Bean들이 있다.
여기서 어떻게 보면 이때까지 프로그래밍 했던 부분과 가장 다른 부분은 객체의 제어를 스프링으로 넘겨주는 IoC였다.
하지만 내가 따로 말도 안해줬는데 그냥 가만히 있으면 스프링이 알아서 코드에서 Bean을 찾는 것도 아니고, 도대체 어떻게 관리할 객체를 찾을까??
스프링피셜
물론 스프링이 알아서 찾아서 한다는 건 말이 안된다. 정확히 말하자면 알아서 하기는 하지만 적어도 어느 부분을 참조해서 알아서 해라 라고 정해줘야 스프링도 어느정도 일을 할 수 있다.
여기서 나오는 것이 @Component이다.
@Component 어노테이션은 Configuration 파일에 Bean을 따로 등록하지 않아도 클래스를 Bean으로 사용할 수 있도록 설정해주는 어노테이션이다..
빈 등록자체를 빈 클래스 자체에다가 할 수 있다는 의미이다.
물론 Configure파일에서 처리해도 되지만 이렇게 클래스위에 어노테이션을 달아 간단히 처리해 줄 수도 있다.
근데 그럼 파일이 어느 위치에 있던 @Component만 있으면 다 스프링에게 맡길 수 있는 것일까?
그건 또 아니다.
만약 그렇게 된다면 내 컴퓨터의 @Component로 처리된 모든 클래스가 스프링에게 관리되는 말도안되는 일이 벌어질 것이다.
이를 위해 @ComponentScan이 나오게 된다.
@ComponentScan이 붙은 클래스의 위치를 기반으로 @Component를 검사하게 되는데 이는 스프링을 생성하게 되면 기본적으로 있는 main메서드에 붙어 있는 @SpringBootApplication에 위치한다.
이를 통해 전체적으로 main메서드와 같은 위치 상(하위 포함)에 있다면
Component어노테이션 및 @Service, @Repository, @Controlle와 같은 어노테이션이 등록된 Class들을 모두 스캔하여 관리해 줄 수 있게 된다.
이렇게 Component어노테이션으로 등록된 Bean객체를 사용할 때에는 IoC컨테이너로 알아서 자동 생성되며 Singleton 패턴을 따르기 때문에 초기에 한번만 생성되고 그 뒤로는 생성된 객체를 계속해서 사용하게 된다.

싱글톤 벙글톤
그렇다면 Autowired 어노테이션은 뭘까??
집단 지성을 통해 4명이서 토론한 결과 나온 대답은 이러했다.
_클래스(스프링 빈)에서 DI를 통해 사용될 수 있는 경우가 3가지가 경우가 있는데
1.필드 2.생성자 3.메소드
@Autowired 어노테인션을 이용해 이 모든 경우에 DI를 스프링에 요청할 수 있다._
이렇게 보면 DI를 요청하는 어노테이션인가? 라고 생각할 수 있다.
그게 맞다.
의존성을 주입해주는 방식 중 하나로 이 어노테이션을 통해 의존성을 주입해 줄 수 있다.
여기서 Autowired는 기본값이 true이기 때문에 의존성 주입을 해줄 객체를 찾지 못한다면 실행되지 않고 에러가 발생한다고 한다.
무작정 막 쓰다가는 에러가 발생한다는 얘기..
Autowire를 통해 DI를 할때의 3가지 경우의 장단점은 다음과 같다.
1.필드
간단하게 선언하여 처리할 수 있지만 의존관계를 눈으로 보기 쉽지않고 DI container와 강한 결합력을 갖기 때문에 외부에서 사용하기 힘들다. (예를 들어 test 코드를 작성할때 test코드에서 제어 할 수 없고 직접 실제 코드에서 수정을 해줘야 함.)
이러한 문제점 때문에
2.setter
의존성이 선택적으로 필요한 경우를 대비하기 위해 setter에 autowire를 설정하여 의존성을 주입하는 경우가 생겼다.
하지만 이 경우에는 너무 과도하게 가변적?으로 사용될 수 있다는 단점이 존재했다.
그래서 이 둘을 섞어 적당히 불변이고 적당히 가변인 뭔가 말인거 같은데 말이 아닌거 같은 방식이 나왔다.
3.생성자
생성자를 통해 순환참조를 막고 의존성 주입 대상 필드를 final로 정의할 수도 있으며(위에 2개는 못한다.) 요즘 다들 한다는 테스트 코드를 작성할 때에 의존성을 주입해주는데에도 용이하다.
물론 완벽하게 순환참조를 막지는 못하지만 이건 어쩔 수없는 단점이라고 생각했다.
추가적으로 생성자가 1개일 경우에는 autowire를 생략할 수 있어, 만약 autowire를 안썼는데 잘 돌아갈 때에는 이런 경우일 가능성도 생각해 보아야 한다.
이렇듯 스프링은 공부하면 공부할 수록 객체를 컨트롤 하는데에 많은 방법과 형식이 사용된다.
이때까지 그냥 아무생각없이 사람들이 써서 나도 썼다.였다면 이제 부터는 이렇기 때문에 나는 얘를 썼다.
라는 마인드가 될 수 있도록 더 공부하겠다.

아 졸리다
스프링처럼 유익한 글이네요