CS

S)Spring_09_스프링 컨테이너

99duuk 2024. 4. 10. 22:06

스프링 컨테이너란?

 

스프링에서 자바 객체는 Bean이라고 한다.
스프링 컨테이너는 bean의 생명 주기를 관리(생성, 관리, 제거 등)하며, 생성된 bean에 추가적인 기능을 제공한다.

더보기

객체(Object):

객체는 일반적으로 소프트웨어에서 사용되는 모든 것을 말한다.

클래스의 인스턴스가 되어 메모리에 할당된 것을 의미한다.

자바에서는 클래스를 기반으로 객체를 생성하고, 이들은 메서드를 호출하거나 변수에 접근할 수 있다.

 

빈(Bean):

스프링에서의 빈은 스프링 컨테이너에 의해 생성, 관리 및 제어되는 객체를 의미한다.

빈은 스프링의 IoC 컨테이너에 등록되어야 하며, 스프링 컨테이너가 애플리케이션의 제어를 가져갈 수 있도록 한다.

빈으로 등록된 객체는 스프링의 라이프사이클에 따라 생성되고 소멸되며, 스프링의 다양한 기능을 활용할 수 있다.

 

 

비유 해보자면,, 

객체는 사람이다. 사람은 일상적으로 우리 주변에서 볼 수 있는 다양한 형태의 존재다.

 

빈은 특정한 목적을 가지고 선택된 사람들, 즉 특정한 역할을 수행하는 사람들이다.

예를 들어, 음식을 만드는 요리사, 서류를 처리하는 사무원 등 특정한 기능을 가지고 있으며, 그에 맞는 역할을 수행하는 사람들이 빈이 될 수 있다.

 



스프링 컨테이너에는 Beanfactory, ApplicationContext 두 종류의 인터페이스로 구현되어 있다. 
beanfactory는 bean의 제어(생성과 관계설정 같은 것)를 담당하는 IoC 오브젝트이다.
ApplicatoinContext는 beanfactory를 좀 더 확장한 것이다. 
(ApplicationContext가 주로 사용된다. )

 

BeanFactory: 스프링 컨테이너의 최상위 인터페이스로.

빈을 등록하고 생성하며 조회하는 등의 기본적인 빈 관리 기능을 제공한다.

주로 빈의 제어를 담당하고,

getBean() 메서드를 통해 빈을 인스턴스화할 수 있다.

 

ApplicationContext: BeanFactory의 기능을 상속받아 확장된 인터페이스로,

빈 관리 기능 및 다양한 부가 기능을 제공한다.

부가 기능은 메시지 다국화, 환경 변수 처리, 이벤트 관리, 리소스 로딩 등이 포함된다.

 

또한 빈을 미리 로드하여 애플리케이션 시작 시간을 최적화할 수 있다.

대부분의 경우에는 ApplicationContext를 사용하는 것이 권장된다.

[부가 기능]

더보기

MessageSource (메시지 다국화 위한 인터페이스)

 

EnvirmentCapable (개발, 운영, 환경변수 등으로 나누어 처리하고, 어플리케이션 구동 시 필요한 정보 관리하기 위한 인터페이스)

 

ApplicationEventPubliser (이벤트 관련 기능을 제공하는 인터페이스)

 

ResourceLoader (파일, 클래스, 패스, 외부 등 리소스 편하게 조회)

 

 

 

스프링 컨테이너는 bean을 넣어둔 상자다.
애플리케이션 실행 중에 필요한 bean이 있으면, 스프링은 상자에서 bean을 주입받아 사용한다.
이렇게 스프링 컨테이너는 bean의 생명 주기 관리와 DI를 담당한다.

 


스프링 컨테이너의 기능

 

Bean의 인스턴스화, 구성, 전체 생명 주기를 관리한다. 

- 개발자가 bean을 정의하고, 컨테이너는 bean을 객체로 만들고 필요할 때 제공한다.

 

스프링 컨테이너를 통해 원하는 만큼 많은 객체를 가질 수 있다.


DI를 통해 애플리케이션의 컴포넌트를 관리할 수 있다.

스프링 컨테이너는 서로 다른 bean을 연결해 애플리케이션 bean을 연결하는 역할을 한다.
- 개발자는 모듈 간 의존 및 결합으로 발생하는 문제로부터 자유로워진다.

- 메서드가 언제 호출 될지, 메서드를 호출하기 위한 매개 변수를 준비해서 전달하지 않는다. 

 


스프링 컨테이너의 사용 이유

느슨한 결합 / 의존성 제거

 

객체를 생성하기 위해서는 new 생성자를 사용해야 한다. 
그로 인해 수많은 객체가 존재하고 서로 참조하게 된다.

객체 간 참조가 많으면 많을수록 의존성이 높아지게 된다. 

(낮은 결합도와 높은 캡슐화를 지향하는 객체지향 프로그래밍의 핵심과 먼 방식이다.)

 

객체 간의 의존성을 낮추어(loose coupling) 결합도는 낮추고, 높은 캡슐화를 위해 스프링 컨테이너가 사용된다.

 

 

기존 방식으로는 새로운 기능을 추가했을 때, 변경 사항을 수작업으로 수정해야 한다. 

프로젝트의 크기가 커질수록 의존도가 높아질 것이고, 변경 사항에 대한 코드 변경도 많아진다. 

하지만 스프링 컨테이너를 사용하면 구현 클래스에 있는 의존성을 제거하고

인터페이스에만 의존하도록 설계할 수 있다.

 


스프링 컨테이너의 생성 과정

(xml을 통해 직접 설정해주어야 했지만)

주로 java의 어노테이션으로 설정하게 된다. 

 

 

- 비어있는 스프링 컨테이너 생성 (초기화)

- 스프링 설정 파일 기반 bean 등록

- bean 의존 관계 주입

 

 

 

 

 

 

 


Singleton pattern

생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고,

최초 생성 이후 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. 

 

 

> why?

계속 새로운 객체를 생성하면 메모리 낭비가 심하기 때문에 사용한다.

 

 

스프링 컨테이너와 Singleton

 

스프링 컨테이너는 싱글톤으로 bean을 관리한다.

 

 

스프링에서 빈의 기본 스코프는 싱글톤이다.
(스프링 컨테이너가 애플리케이션 전체에서 하나의 인스턴스만 생성하고 관리한다.)
싱글톤 패턴을 사용해 빈의 인스턴스를 생성하고 관리한다.

스프링이 빈을 싱글톤으로 관리하는 것은 메모리 사용을 최적화하고 애플리케이션 성능을 향상시키는 데 도움이 된다.
애플리케이션 여러 곳에서 동일한 빈을 사용할 경우, 
각각의 빈을 매번 생성하는 것보다 싱글톤으로 관리함으로써 
메모리 사용을 줄이고 객체 생성 비용을 절약할 수 있다.

스프링 컨테이너가 싱글톤 패턴을 사용해 빈을 관리하면 
애플리케이션 전체에서 일관된 상태를 유지할 수 있다.
각각의 빈이 동일한 인스턴스를 공유하기 때문에 상태의 일관성이 보장된다. 

객체 간의 의존성이 효과적으로 관리된다. 
동일한 빈을 여러 곳에서 사용할 때 
각각의 빈이 동일한 인스턴스를 참조하므로 의존성 주입이 용이해진다. 

 

[스코프]

더보기

빈의 스코프는 빈이 생성되고 사용되는 범위를 나타낸다.

(생명 주기를 관리)

 

스프링에서는 주로

싱글톤,

프로토타입,

요청(request),

세션(session),

application 등

스코프를 지원한다.

 

 

 

 

> 주의점

객체 인스턴스를 공유하기 때문에 객체 상태를 유지(stateful)하게 설계하면 안된다.

 

 

객체 상태를 유지(stateful)하게 설계한다는 것은

객체가 내부적으로 상태를 가지고 있어서

그 상태가 변경될 수 있다는 것을 의미한다.

 

-> 객체가 다양한 메서드 호출에 따라 상태가 변할 수 있다.

(객체가 다양한 상황에 대응하기 위해 상태를 계속 유지하고 갱신해야 한다)

 

 

 

우리가 레스토랑에서 웨이터에게 주문하는 상황을 떠올려보자.

 

Stateless(상태가 없는) 방식: 웨이터가 주문을 받고 나서 주문서를 요리사에게 전달하고, 요리사가 요리를 만들어 고객에게 제공한다.

이 과정에서 웨이터는 주문을 받고 요리를 전달하는 역할만 하고,

자신이 받은 주문에 대한 상태를 유지하지 않는다.

각 주문은 독립적으로 처리되며, 웨이터는 각 주문의 상태를 신경쓰지 않는다.

 

Stateful(상태가 있는) 방식: 웨이터가 주문을 받고 나서 주문 내용을 메모장에 기록한 후, 요리사에게 전달하고,

요리가 완료되면 고객에게 제공한다.

이때 웨이터는 각 주문에 대한 상태를 메모장에 유지한다.

따라서 웨이터가 주문을 처리하는 동안에는 해당 주문에 대한 상태를 계속해서 갱신하고 관리한다.

 

 

 

여기서 웨이터가 메모장에 주문 내용을 기록하고 유지하는 것이 객체의 상태를 유지하는 것과 유사하다.

Stateful한 설계에서는 객체가 메모장과 같이 상태를 유지하며,

객체의 메서드 호출에 따라 상태가 변경될 수 있다.

 

이러한 Stateful한 설계는 보통 객체의 복잡성과 의존성을 증가시키며,

예측이 어렵고 디버깅이 어려워질 수 있다.

 

따라서 객체의 상태를 최소화하여 Stateless한 방식으로 설계하는 것이 권장된다.

 

 

 

 

Stateless한 설계

객체가 상태를 유지하지 않고,

각 요청 또는 메서드 호출이 독립적으로 처리된다.

 

이러한 방식은 객체의 복잡성을 줄이고 의존성을 관리하기 쉽게 만든다.

또한 예측 가능하고 디버깅이 용이하며,

확장성이 뛰어난 코드를 작성할 수 있게 된다.

 

 

 

 

 

 

'CS' 카테고리의 다른 글

CS)Spring_10_빈 라이프 사이클  (0) 2024.04.25
S)Spring_10_스프링 컴포넌트 스캔 Component Scan & DI 자동 주입  (0) 2024.04.15
S)Spring_09_스프링DI  (0) 2024.04.09
S)DB_08_JOIN  (0) 2024.04.02
S)DB_08_DBCP  (0) 2024.04.02