22/02/21 TIL

Jaden.dev·2022년 2월 21일
0

📌 Component Scan

스프링에서 Component Scan 이란?

@Component 어노테이션을 가진 대상을 빈(Bean)에 등록하기 위해 찾는 과정

기본으로 스캔하는 대상

  • @Component
  • @Controller
  • @Service
  • @Repository
  • @Configuration

위 어노테이션 중 컨트롤러, 서비스, 레포지토리 어노테이션은 직접 들어가보면 @Component 어노테이션이 내부에 존재함을 알 수 있다. @Configuration 의 경우 스프링 설정 정보 클래스로, 내부에 @Bean 어노테이션들이 선언되있으면 해당 메서드들을 빈에 등록한다.
@ComponentScan 어노테이션이 있는 파일의 패키지 아래를 다 scan하게 되는데, SpringBoot를 사용하면 @SpringBootApplication 에 포함되어있어 자동으로 최상단에 유지된다.

그렇다면 Bean 이란?

스프링 IoC 컨테이너가 관리하는 자바 객체를 빈(Bean)이라고 부른다.

@Bean vs @Component

@Bean 의 경우 개발자가 컨트롤이 불가능한 외부 라이브러리들을 Bean으로 등록하고 싶은 경우 사용할 수 있다.

@Bean
public ObjectMapper objectMapper() { return new ObjectMapper(); }

직접 컨트롤이 가능한 class의 경우에는 @Component 를 사용할 수 있다.
@Bean@Target 이 METHOD, @Component@Target 이 TYPE이라 각각 메서드 위, 클래스 위에서 사용될 수 있다.

Component Scan

그래서 스프링은 결국 @Component, @Configuration 을 scan하여 이 객체들을 Bean에 등록하고 관리한다. @Configuration 에는 @Bean 어노테이션이 붙은 객체 생성 메서드들이 존재하므로 이들도 스캔 후 등록한다.

참고자료

📌 DIP, IoC

DIP (Dependancy Inversion Principle)

고수준의 모듈은 저수준 모듈의 구현에 의존해서는 안 된다. 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다. -> 자신보다 변하기 쉬운 것에 의존하지 마라. 코드의 의존은 변할 가능성이 적은 것에 의존할수록 좋다.

차량에 스노우 타이어를 끼도록 설계하였다. 그러나 날씨가 따뜻해지면서 스노우 타이어를 사용할 필요가 없어졌다. 일반 타이어로 교체하는 것으로 끝나는게 아니라, 이에 의존하고 있던 차량의 코드에도 영향을 끼친다. 이는 적절하지 않기 때문에, 추상화를 통해 문제를 해결해야 한다.
스노우타이어나 일반타이어를 '타이어'라는 것으로 추상화 하는 것이다.

그러나 소스코드의 의존은 차량을 의존하지만, 런타임에서의 객체 의존은 타이어가 아닌 하위 타이어 중 하나를 의존한다. 런타임에서의 의존을 역전시키는 것은 아니라, 소스코드 단계에서의 의존을 역전 시키는 것.

DI(Dependancy Injection)

  • Setter Injection
  • Constructor Injection
  • Method Injection

의존성 주입과 Bean 등록은 다르다. 일단 IoC 컨테이너에 빈으로 등록이 되어야 의존성을 주입할 수 있다.

IoC(Inversion of Control)

  • 일반적으로 자바 프로그램에서는 각 객체들이 프로그램의 흐름을 결정하고, 객체를 직접 생성하고 조작하는 작업(객체를 생성(new)하여 메서드 호출)을 했다.
  • 예를들어 A 객체가 B 객체 내에 있는 C 메서드를 사용하고 싶으면, A 객체 내에서 B 객체를 직접 생성하고 C 메서드를 호출한다.
  • IoC가 적용된 경우, 객체의 생성을 관리 위임 주체에게 맡긴다. 사용자는 객체를 직접 생성하지 않고, 객체의 생명주기를 컨트롤하는 주체는 다른 주체가 된다. 이렇게 사용자의 제어권을 다른 주체에게 넘기는 것을 IoC라고 한다.

예를들어, 손님이 음식을 주문하고 주문한 음식을 요리해서 나오는 워크 플로우가 있다고 가정하자.

  • 셰프가 직접 요리를 주문받는다면, 셰프는 요리를 주문받고 해당 요리를 위해 필요한 요리사들을 불러서 각 파트를 요리하게 한 후, 이들을 조합하여 요리를 완성하고 내놓는다.
  • 이에 반해 요리의 주도권을 주방에 넘기고 주문만 받는 역할만 수행한다면, 주문을 받고 음식을 내놓는 사람은 주방에서 무슨일이 일어나는지 알 필요가 없다. 요리의 이름을 전달하고, 해당 요리를 받아서 내놓기만 하면 되기 때문이다.

제어의 역전은 프레임워크와 라이브러리를 구분하는 열쇠이기도 하다. 라이브러리는 우리가 호출할 수 있는 기능의 집합이고, 프레임워크는 우리가 만들어놓은 기능을 호출하는 대상이다.

📌 스프링 컨테이너

스프링 컨테이너는 Bean FactoryApplicationContext 두 가지 유형이 존재한다.
객체의 인스턴스를 싱글톤으로 관리해서 싱글톤 컨테이너라고도 불린다(?).

Bean Factory

스프링 설정파일에 등록된 Bean 객체를 생성하고 관리하는 기본적인 기능을 제공.
컨테이너가 구동될 때 Bean 객체를 생성하는 것이 아니라 클라이언트의 요청에 의해서 Bean 객체가 사용되는 시점에 객체를 생성하는 Lazy Loading 방식을 사용하고 있다.

ApplicationContext

앞서 언급한 Bean Factory 를 상속받아 Bean 객체를 생성하고 관리하는 기능을 가지고 있다. 또한 트랜잭션 관리, 다국어 처리, AOP 처리 등 많은 부분을 지원한다.
컨테이너가 구동되는 시점에 객체들을 생성하는 Pre-Loading 방식이라는 점이 가장 큰 차이다.

📌 궁금한 점

  • @Configuration 어노테이션을 사용하지 않으면 @Bean 의 싱글톤을 보장할 수 없다. 왜? 싱글톤으로 Bean을 관리하려면 @Configuration 을 꼭 붙일 것.
  • @AutoWired 어노테이션
profile
https://github.com/JadenHeo

0개의 댓글