IoC/DI & Spring Bean Life Cycle
해당 내용은 DOM의 발표자료 를 참고하여 재구성하였습니다. 자세한 설명은 해당 사이트를 통해 확인하시길 바랍니다.
오늘은 Container에 대해 알아볼려고 합니다. 그 이전에 어제 다루었던 IoC(Inversion of Control)에 대해 다시 한번 살펴보고 넘어가겠습니다.
IoC(Inversion of Control) 리뷰
프레임워크를 사용하기 전에는 애플리케이션 내에 있는 코드가 주체가 되어 필요할 때마다 호출되었습니다. 하지만 프레임워크 기반의 애플리케이션은 애플리케이션 코드들이 주체가 되는 것이 아니라 프레임워크가 주체가 되어 필요에 따라 호출되어 사용되게 됩니다.
Spring 프레임워크 내에서 이렇게 관리해주는 주체가 되는 것이 Container
입니다. 여기서 이제 IoC에 대한 개념이 나오는데요. 객체에 대한 제어권이 개발자로부터 컨테이너로 넘어가고, 컨테이너에서 객체의 생성부터 관리까지 모든 것을 담당하게 됩니다. 이렇게 제어의 흐름이 바뀌었다고 해서 '제어의 역전(IoC, Inversion of Control)' 이라고 합니다.
출처 : https://jongmin92.github.io/2018/02/11/Spring/spring-ioc-di/
Container
출처 : https://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/beans.html
Spring IoC container는 의존성이 없는 평범한 하나의 객체인 POJOs(Plain Old Java Objects)를 받아 Configuaration Metadata에 따라 객체를 초기화, 설정, 기존 bean과 조립하는 역할을 합니다. Configuration Metadata는 XML, 자바 Annotation, 자바코드에 의해 표현될 수 있습니다. 이를 통해 평범한 객체에 불과했던 POJOs는 의존성이 주입된 객체들로 만들어지는 것이죠.
그럼 왜 사용하는 것일까요?
굳이 이런 Spring IoC container를 사용하지 않더라도 사실 factory클래스를 이용하여 필요한 해당 객체가 왔을 때 그에 맞는 객체를 반환시켜 의존성을 주입할 수도 있습니다. 그럼에도 불구하고 컨테이너를 사용하는 이유는 객체 간의 의존성을 낮추고 확장성을 고려하기 위함입니다.
의존성을 낮추고 확장성을 고려한다?
static {
figures.put(NUM_FOR_LINE, new LineFactory());
figures.put(NUM_FOR_TRIANGLE, new TriangleFactory());
figures.put(NUM_FOR_SQUARE, new SquareFactory());
}
위 코드는 지난 미션에서 factory클래스를 이용하여 그에 맞는 객체를 생성해주는 코드입니다. 이렇게 팩토리 클래스로 사용되는 것의 단점은 위와 같이 미리 매핑을 시켜놔야 한다는 것입니다. 만약 Line
, Triangle
, Square
가 아니라 팔각형이 필요하다면 octagonFactory()
클래스를 미리 만들어놓고, 저기 static블록 안에도 figures 안에 매핑시켜놓아야 할 것입니다. 하지만 Container를 사용하면 굳이 저러한 작업을 하지 않아도 새로 만들어둔 클래스로 명시해놓고 주입만 시키면 되는 것이죠. 그런 점에서 코드상의 의존성을 낮추고 확장성이 더 좋아진다고 할 수 있죠.
이러한 Container의 중추적인 역할을 담당하는 인터페이스가 BeanFactory
와 ApplicationContext
입니다. 두 개의 인터페이스는 Bean의 등록/생성/조회/반환/관리를 한다는 점에서 같지만 ApplicationContext
는 BeanFactory
를 확장하여 좀 더 추가적인 서비스를 제공한다는 점에서 차이가 있습니다.
Bean의 종류 및 의존성 주입
어제 의존성을 주입하기 위한 여러가지의 방법을 다루었는데요. SpringBoot에서는 Annotation을 통해서 Bean을 설정하는 것을 표준으로 삼고 있습니다. 그럼 Annotation을 통해 Bean을 어떻게 설정하는지 살펴볼까요?
SpringBean으로 등록시켜주는 Annotation은 다음과 같이 다섯가지가 있습니다.
@Bean, @Component, @Controller, @Service, @Repository
@Bean
과@Component
의 차이점은?- 활용 부분에 있어 차이점이 있는데요.
@Bean
은 보통 개발자가 접근할 수 없는 외부 라이브러리에 사용하고,@Component
는 개발자가 만든 클래스 등에 사용된다고 합니다. - 이렇게 활용부분에 차이점이 있는 이유는 두 개의 정의된 Target이 다르기 때문입니다.
@Bean
의 경우 메서드 레벨,@Component
는 클래스 레벨에서 사용되기 때문입니다. - 즉, 외부 라이브러리의 경우 클래스에 접근 권한이 없기 때문에 메서드의 return값을 Bean으로 사용해야하기 때문에
@Bean
을 사용합니다. 반면 사용자 정의 클래스는 바로 접근 가능하고 또 클래스 레벨에서 사용되기 때문에 그 경우엔@Component
를 사용하는 것입니다. @Bean
등록은@Configuration
이 있는 클래스에서 등록이 가능합니다!
- 활용 부분에 있어 차이점이 있는데요.
이렇게 등록된 Bean은 @Autowired
라는 Annotation이 붙은 객체에 DI컨테이너에 의해 타입 또는 이름에 의해 찾아서 주입되게 됩니다.
@Autowired 말고 @Resource도 있던데 그것과의 차이는 무엇일까요?
두 개의 주요한 차이는 @Autowired
는 type에 따라 연결시켜주고, @Resource
는 Bean name에 따라 연결시켜준다는 것입니다. 하지만 @Autowired
와 @Qualifier
의 조합으로 Bean name으로 연결시켜줄 수도 있습니다.
음.. 테스트로 @Autowired하고 @Qualifier없이 돌려보았는데 객체 이름에 따라 연결시켜주더라구요. 하지만 분명하게 명시하는 것이 좋겠죠!
위에서 @Component
이외에 @Controller
, @Service
,@Repository
어노테이션들이 있었는데요. 이 Annotation들은 어느 레이어에 배치되느냐에 따라 사용하는 것이 좋습니다. 레이어에 대해선 추가적인 공부가 더 필요할 것 같네요..
오늘은 Container와 Bean 종류 및 의존성 주입에 대해서 알아보았습니다. 내일은 Spring Bean의 LifeCycle에 대해 알아볼게요!
'Spring' 카테고리의 다른 글
AOP2 (0) | 2018.12.13 |
---|---|
AOP (0) | 2018.12.11 |
devtools 사용법 (0) | 2018.12.08 |
IoC/DI & Spring Bean Life Cycle3 (0) | 2018.12.06 |
IoC/DI & Spring Bean Life Cycle1 (0) | 2018.12.04 |