Application/Spring Framework

[Spring] IoC 컨테이너와 DI와 빈의 스코프

반응형

IoC 컨테이너와 DI


IoC란?

스프링에서는 오브젝트의 생성, 제거, 사용 및 주입 등의 작업을 개발자가 직접 애플리케이션 코드에 작성하는 대신 독립된 컨테이너가 담당한다. 이를 컨테이너가 코드 대신 (빈) 오브젝트에 대한 제어권을 가지고 있다 해서 IoC (Inversion Of Control)이라고 한다.

 

IoC 컨테이너 vs 빈 팩토리 vs 애플리케이션 컨텍스트

스프링에서는 IoC를 담당하는 컨테이너를 빈 팩토리 또는 애플리케이션 컨텍스트라고 부르기도 한다. 단순히 오브젝트의 생성과 오브젝트 간의 런타임 관계를 설정하는 DI 관점으로 볼때는 빈 팩토리라고 하지만, 스프링 컨테이너는 단순한 DI 작업외에도 더 많은 일을 한다 그래서 더 큰 관점에서 애플리케이션 컨텍스트라고 부르기도 한다.

 

IoC 컨테이너가 어떻게 빈 오브젝트를 관리할까?

POJO 클래스를 애플리케이션에서 사용할 것들을 IoC 컨테이너가 제어할 수 있도록 적절한 메타 정보를 만들어 줘야 한다. 이때, 스프링 컨테이너가 관리하는 오브젝트빈 오브젝트라고 한다.

스프링 IoC 컨테이너는 각 빈에 대한 정보를 담은 설정 메타정보를 읽어 들인 뒤에 이를 참고해서 빈 오브젝트를 생성하고, 프로퍼티나 생성자를 통해 의존 오브젝트를 주입해준다. (DI)

따라서 스프링 애플리케이션이란 POJO 클래스설정 메타정보를 이용해 IoC 컨테이너가 만들어주는 오브젝트의 조합이라고 할 수 있다.

 

자동인식을 위한 빈 등록

모든 빈을 일일이 선언하는 것은 매우 귀찮음.

스프링5부터는 빈으로 사용될 클래스에 특별한 애노테이션을 붙여주고, 이런 클래스를 자동으로 찾아서 빈으로 등록하면, 빈 스캐닝을 통한 자동인식 빈 등록

여기서 빈으로 사용될 클래스에게 @Component 등의 애노테이션을 지정하는 것만으로도 빈 등록이 가능하다. 이때 @Component를 포함해 디폴트 필터에 적용되는 애노테이션을 스프링에서는 stereotype 애노테이션이라고 한다.

컴포넌트 스캔 (스프링 빈 스캐너)는 지정된 클래스 패스 아래에 있는 모든 패키지의 클래스를 대상으로 필터를 적용해서 빈 등록을 위한 클래스들을 선별해, 자동으로 빈으로 등록한다.

 

자바 코드에 의한 빈 등록

@Configuration과 @Bean이 붙으면 스프링 컨테이너가 인식할 수 있는 빈 메타정보 겸 빈 오브젝트 팩토리가 된다

 

빈의 종류

애플리케이션 로직 빈

  • 일반적으로 애플리케이션 로직을 담고 있는 주요 클래스의 오브젝트가 빈으로 지정된다. DAO, 서비스 오브젝트, 컨트롤러 오브젝트 등이 대표적임

 

애플리케이션 인프라 빈

  • DataSource와 같이 DAO가 동작하려면 DB와의 연결을 담당하는 DataSource 타입의 오브젝트가 필요하다. 이때 구현 클래스가 여러 가지여서 하나를 지정하고 연결 방법과 관련된 속성은 코드 외부에서 제공하는 경우가 일반적이라, 빈으로 사용하기에 적당한 오브젝트
  • 애플리케이션의 로직을 직접 담당하지 않음.

 

컨테이너 인프라 빈

  • 스프링 컨테이너가 빈을 생성할 때 프록시 생성 같은 특별한 작업을 하도록 지원해주는 빈

 

빈의 스코프


먼저 빈의 스코프란 빈 오브젝트가 만들어져 존재할 수 있는 범위이다. 빈 오브젝트의 생명주기 (라이프 사이클)은 스프링 IoC 컨테이너가 관리하기 때문에 대부분 정해진 범위의 끝까지 존재한다.

기본적으로 빈은 싱글톤으로 만들어진다.

 

  • 싱글톤: 애플리케이션 컨텍스트 마다 빈의 오브젝트는 단 한 개만 만들어진다.
  • 프로토타입: 반대로 여러 개 만들어질 수 있음


싱글톤

그럼 기본적으로 빈은 싱글톤으로 만들어지는 이유가 무엇일까?

 

사용자의 요청이 있을 때마다 매번 애플리케이션 로직을 담은 오브젝트를 새로 만드는 것 매우 비효율적임.

싱글톤 객체는 하나의 빈 오브젝트에 동시에 여러 스레드가 접근하기 때문에 상태 값을 인스턴스 변수에 저장해 두고 사용할 수 없어 읽기 전용 값만 저장해둬야 하는데, 애플리케이션 로직을 담은 오브젝트는 대부분 싱글톤 빈으로 만들면 충분하다.


프로토타입

프로토타입 스코프를 갖는 빈은 요청이 있을 때마다 컨테이너가 생성하고 초기화해주고 DI까지 해준다. 하지만 싱글톤 빈과는 다르게 일단 빈을 제공하고 나면 컨테이너는 더 이상 빈 오브젝트를 관리하지는 않는다.

그러면 이렇게 매번 새로운 빈을 만들어주는 프로토타입 빈은 어떤 경우에 사용할까?

⇒ 서버가 요청에 따라 독립적으로 오브젝트를 생성해서 상태를 저장해둬야 하는 경우는 도메인 오브젝트나 DTO를 new 키워드를 생성하고 파라미터로 전달해서 사용하면 된다. (여기서 DTO와 도메인 오브젝트는 빈이 아닙니다)

프로토타입 빈은 이렇게 코드에서 new로 오브젝트를 생성하는 것을 대신하기 위해 사용된다.

사용자의 요청에 따라 매번 독립적인 오브젝트를 만들어야 하는데, 그 오브젝트에 DI를 적용하려면 컨테이너가 오브젝트를 만들게 해야 한다. 이럴 때 프로토타입 빈이 사용된다.

(예를 들어서 도메인 객체에서 빈을 의존성 주입을 받아서 사용하고 싶을 때, 도메인 객체를 프로토타입 빈으로 만들어 줘야 스프링 컨테이너가 관리하는 빈에 대해서 의존성 주입을 받을 수 있다.)

코드 내에서 필요할 때마다 컨테이너에게 요청해서 새로운 오브젝트를 만들어야 하는 프로토타입 빈은 DI를 사용하기에 적합한 방법이 아니다. 따라서 DL 방식으로 사용해야 한다.


이외의 빈의 스코프

위의 싱글톤, 프로토타입 스코프 외에 스프링에서는 요청, 세션, 글로벌 세션, 애플리케이션이라는 네 가지 스코프를 기본적으로 제공함.

  • 요청 스코프: 하나의 웹 요청 안에서 만들어지고 해당 요청이 끝날 때 제거된다.
  • 세션 스코프, 글로벌 세션 스코프:  글로벌 세션 스코프는 포틀릿에만 존재하는 글로벌 세션에 저장되는 빈, HTTP 세션과 같은 존재 범위를 갖는 빈으로 만들어주는 스코프. HTTP 세션을 직접 스프링에서 이용하는 건 매우 귀찮고 번거로운 작업임 ⇒ 스프링에서 웹 기술에 종속적이지 않은 오브젝트에 담아서 HTTP 세션에 직접 접근 가능한 프레젠테이션 계층과 서비스 계층 사이에 주고받을 수 있게 해 주고 위함
  • 애플리케이션 스코프: 서블릿 컨텍스트에 저장되는 빈 오브젝트

 

출처) 토비의 스프링3.1 Vol.2 스프링의 기술과 선택

반응형