스프링 컨테이너와 싱글톤 컨테이너에 대해서 알아보자
들어가며
이 블로그 포스트에서는 스프링 프레임워크에서 핵심적인 역할을 하는 "스프링 컨테이너"와 그 중요한 개념인 "싱글톤 컨테이너"에 대해 알아보겠습니다. 스프링의 핵심인 이 두 가지 개념을 이해하고 활용함으로써 좀 더 효율적이고 안정적인 애플리케이션을 개발할 수 있습니다.
스프링 컨테이너란?
스프링 컨테이너(Spring Container)는 애플리케이션의 구성을 담고 있는 환경으로, 빈(Bean)을 생성하고 관리해 주는 역할을 합니다. 런타임 시에 값을 주입해 주기 위해서는 스프링이 컨테이너에 필요한 정보를 저장해 두고, 필요한 시점에 값을 주입합니다.
일반적으로 @Configuration 어노테이션이 붙은 설정 파일을 통해 스프링 컨테이너에 값을 저장합니다. 이 설정 파일은 스프링이 애플리케이션의 구성을 이해하고 빈을 생성하는 데 사용됩니다. @Bean 어노테이션이 붙은 메서드는 해당 메서드가 반환하는 객체를 빈으로 저장합니다. 빈의 이름은 기본적으로 메서드 이름을 사용하나, 직접 이름을 부여할 수도 있다.
이를 통해 스프링 컨테이너는 애플리케이션의 구성을 유연하게 관리하고, 런타임 시에 필요한 객체들을 생성하고 주입하여 사용할 수 있습니다.
위 그림과같이 Conig라는 설정파일의 두 개의 @Bean이 있다면 스프링 컨테이너에는 메서드 이람과 반환 객체를 통해 스프링 컨테이너에 저장됩니다.
위와 같은 의존 관계를 가지게 됩니다.
조회방법
설정한 스프링 컨테이너의 bean을 조회하는 방법은 다음 명령어를 통해 조회할 수 있다.
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(설정파일. class)
Bean 하나일 때
ac.getbean(빈이름, 타입)
ac.getBean(타입)
조회할 빈이 없다면 Exception발생
Bean 둘이 상일때
ac.getBeadsOfType(타입) : <Map> 형식
스프링 빈 조회 시에 Object타입으로 조회시 자식 타입까지 조회된다.
BeanFactory와 ApplicationContext
BeanFactory와 ApplicationContext는 스프링에서 빈(Bean)을 관리하고 제공하는 역할을 합니다. 두 가지 모두 스프링 컨테이너의 구현체로, 애플리케이션의 객체를 생성하고, 관리하며, 제공합니다. 그러나 두 인터페이스 간에는 몇 가지 차이점이 있습니다.
BeanFactory
- 가장 기본적인 스프링 컨테이너 인터페이스
- 빈(Bean)을 생성하고, 초기화하며, 관리하는 역할
- 위에서 설명한 AnnotationConfigApplicationContext의 최상의 인터페이스
ApplicationContext
- BeanFactory 기능을 모두 상속받아서 제공
- 빈을 관리하고 검색하는 기능을 제공 및 수많은 부가기능을 제공한다.
ApplicationContext 부가기능
- 메시지 소스 처리(MessageSource): 다국어 지원을 위한 메시지 처리 기능을 제공합니다.
- 환경 프로퍼티 처리(Environment): 애플리케이션의 환경 설정 정보를 다룹니다.
- 이벤트 발행 및 처리(ApplicationEvent): 애플리케이션에서 발생하는 이벤트를 처리하고, 필요한 리스너에게 이벤트를 전달합니다.
- 리소스 로딩(Resource Loading): 애플리케이션의 리소스를 로드하고 처리하는 기능을 제공합니다. 클래스패스, 파일 시스템, URL 등 다양한 위치에서 리소스를 로드할 수 있습니다.
- 애플리케이션 콘텍스트 계층 구성: 여러 개의 애플리케이션 콘텍스트를 계층 구조로 구성할 수 있습니다. 부모 애플리케이션 콘텍스트에 정의된 빈을 자식 애플리케이션 콘텍스트에서 공유하거나 재정의할 수 있습니다.
- 프로파일(Profile) 기능: 환경별로 다른 설정을 구성할 수 있습니다. 특정 환경에 따라 빈을 선택적으로 등록하거나 활성화할 수 있습니다.
- 캐싱(Caching): 빈을 생성하고 관리하는 과정에서 발생하는 중복 작업을 최소화하기 위해 캐싱 기능을 제공합니다.
- 테스트 지원(Test Support): 스프링 애플리케이션을 테스트하는 데 도움이 되는 다양한 유틸리티 클래스와 기능을 제공합니다.
ApplicationContext 다양한 형식지원
ApplicationContext는 다양한 형식의 설정 정보를 지원하여 빈(Bean)을 관리할 수 있습니다. 앞서 작성했던 Conifg.class는 에노테이션 기반으로 작성된 설정파일은 그중 하나이며, 다른 형식으로는 XML 등이 있습니다. 따라서 ApplicationContext는 에노테이션 방식뿐만 아니라 XML 등 다양한 형식의 설정 정보를 처리할 수 있습니다.
에노테이션 방식 : AnnotationConfigApplicationContext
xml방식 : GenericXmlApplicationContext
BeanDefinition - 스프링 빈 메타정보
스프링은 에노테이션 @Bean이나 xml의 <Bean>이 붙은 정보 하나당 메타정보를 생성한다. 스프링 컨테이너는 이 메티정보 기반으로 스프링빈을 생성해 준다.
@Configuration이 붙은 설정파일인 Config에는 총 두 개의 @Bean 에노테이션이 붙어있다. 그러면 두개의 메타정보가 생성된다. 생성되는 방법은 다음 과같이 생성된다.
BeanDefinitionReader어댑터를 이용해 @Cofiuration 붙은 설정파일은 가지고 읽고 난 후에 메타 정보를 생성해 준다.
xml도 비슷한 방식으로 동작한다.
BeanDefinition - 메타정보 메서드
- BeanClassName: 생성할 빈의 클래스 명
- factoryBeanName: 팩토리 역할의 빈을 사용할 경우 이름
- factoryMethodName: 빈을 생성할 팩토리 메서드 지정
- Scope: 싱글톤(Default)
- lazyInit: 스프링 컨테이너를 생성할 때 빈을 생성하는 것이 아니라, 실제 빈을 사용할 때까지 최대한 생성을 지연처리 하는지 여부
- InitMethodName: 빈을 생성하고, 의존관계를 적용한 뒤에 호출되는 초기화 메서드 명
- DestroyMethodName: 빈의 생명주기가 끝나서 제거하기 직전에 호출되는 메서드 명
- Constructor arguments, Properties: 의존관계 주입에서 사용한다.
싱글톤 컨테이너
싱글톤 컨테이너는 디자인 패턴의 싱글톤 패턴을 바탕으로 만들어진 스프링의 핵심 기능 중 하나입니다. 싱글톤 패턴과 마찬가지로 하나의 인스턴스만을 생성하고 이를 공유하는데, 스프링의 컨테이너 기술과 결합하여 스프링이 대신 인스턴스를 생성하고 관리해 주는 것이 핵심 기능입니다. 이를 통해 자원을 효율적으로 활용하고 성능을 향상할 수 있습니다.
사용자 A, B, C가 스프링 컨테이너에 서비스를 요청하면, 스프링은 각각의 요청에 대해 새로운 인스턴스를 생성하고 반환합니다. 그러나 만약 1000명의 클라이언트가 요청을 한다면, 컨테이너는 1000개의 인스턴스를 생성하게 되어 메모리 자원을 많이 사용하게 됩니다. 이는 효율적이지 못한 방법입니다.
그러나 싱글톤 컨테이너를 적용한 스프링을 사용한다면, 하나의 인스턴스만 생성하고 요청이 들어올 때마다 해당 인스턴스를 공유하여 반환합니다. 이렇게 함으로써 모든 클라이언트에게 하나의 인스턴스만을 제공하며, 생성과 관리까지 대신해 주는 획기적인 기술입니다. 이를 통해 메모리 자원을 효율적으로 사용할 수 있습니다.
싱글톤 방식의 주의점
싱글톤 방식의 컨테이너를 사용한다면 무상태로 설계해야 한다. 만약 싱글톤 설정 시에 클래스 인스턴스 변수를 선언할 때 final 키워드를 꼭 붙여서 사용해야 합니다 ex) private int sington; 사용 x private fianl int single; 사용 O
다음과 같이 싱글턴인스턴스를 사용해 첫 번째 사용자는 "싱글톤 변경!!"으로 값을 수정했고 이어서 바로 다음 사용자가 "또 변경!!" 이러고 SingleTon 인스턴스를 변경했다고 해보자 그러면 final 키워드를 사용하지 않았을때는 첫번째 사용자가 변경한 "싱글톤 변경" 값이 저장되는 것이 아닌 "또 변경!!" 이 저장되어 원치 않는 값이 나올 수가 있다. 그래서 싱글톤 방식을 사용한다면 꼭 final 키워드를 사용해 무상태로 설정해야 변경할 수 없도록 지정해 줘야 싱글톤이 보장될 수 있다.
@Bean에 반환 인스턴스가 여러 개일 때
다음과 같이 @Configuration 설정파일이 반환 타입이 두 개가 있다고 생각해 보자
@Bean
public SingleTonService singleTonService() {
return new SingleTonServiceImpl(
mySingleTonRepository(),
mySingleA()
);
}
@Bean
public SingleTonRepository mySingleTonRepository() {
return new BlogSingleTonRepository();
}
위에 코드를 보면 mySingleTonRepositoryt()가 두 번 생성되는 것을 볼 수 있다. 그럼 인스턴스는 두 개가 생성돼서 싱글톤 패턴이 적용되지 않는 것인가?라고 생각할 수 있다. 하지만 스프링은 바이트코드를 조작해서 프락시 객채를 생성해서 프록시 객체가 실제 실행될 때 위임을 해주는 역할을 하면서 싱글톤 방식을 사용할 수 있게 해 준다.
다음과 같이 스프링 컨테이너에서는 실제 인스턴스인 SingleTon 인스턴스가 생성되는 것이 아닌 프락시 인스턴스가 생성되어 컨테이너에 등록되면서 요청이 들어오면 단지 값을 위임해 전송받는 역할을 해주며 싱글톤을 보장해 준다.
정리
스프링 컨테이너는 스프링 애플리케이션의 빈을 생성하고 관리하는 역할을 합니다. 이를 통해 빈의 라이프사이클을 관리하고 의존성 주입을 수행합니다. 이 중에서 싱글톤 컨테이너는 스프링에서 사용되는 디자인 패턴인 싱글톤 패턴을 활용하여 빈의 인스턴스를 하나만 생성하고 공유함으로써 메모리를 효율적으로 관리합니다
'Spring > spring' 카테고리의 다른 글
[Spring] 스프링의 객체지향 원리 간단하게 이해하기 (0) | 2024.02.28 |
---|---|
[Spring] "객체지향 디자인 패턴 이해하기: 템플릿 메서드, 전략, 콜백" (1) | 2024.02.07 |
[Spring] 스프링에서의 필터(filter)와 인터셉터(Interceptor) (1) | 2024.02.06 |
[스프링] AOP(Aspect-Oriented-Programming)이해 (0) | 2023.11.22 |
[스프링] 트랜잭션(Transaction)이란 (0) | 2023.11.22 |