토마토바구니
600
2020-07-27 23:27:14 작성 2020-07-28 16:42:13 수정됨
0
508

IoC 컨테이너 및 싱글톤/프로토타입


안녕하세요.

스프링과 자바를 공부하고 있는 컴공과 복수전공 학생입니다. 혼자서 공부를 하면서 요약정리 겸 해서 블로그를 하고 있는데요. 저의 블로그에 혹시나 잘못 된 정보가 있어서 혼란을 줄 수 있기 때문에, 혹시나 하는 마음으로 검증을 받을 겸 저처럼 잘 모르는 분들을 위해서 초보끼리 정보를 공유하고자 올립니다.

지적은 환영합니다!




1. IoC container

IoC container는 IoC, 즉 Inversion of Control(제어의 역전)을 가능하게 해주는 컨테이너 입니다. 이 컨테이너는 빈이 생성될 때 의존성을 주입하고, 빈들의 인스턴스화를 해주는 빈을 관리하는 컨테이너 입니다. 


하지만 스프링 API를 보시면 IoC Container가 어떤 클래스나 인터페이스로 존재하는 것이 아닙니다. 즉 IoC를 가능하게 해주는 컨테이너라는 패턴 혹은 프로그래밍 기법이라고 생각하시면 됩니다.


그렇다면 실질적으로 스프링 프레임워크는 어떤 인터페이스나 클래스를 정의해서 빈들을 관리하고 있을까요?


2. BeanFactory interface

스프링 프레임워크에서 실질적으로 빈들을 관리하는 핵심적이고 근본이 되는 것은 BeanFactory 인터페이스 입니다. 이 BeanFactory는 기본적으로 여러개의 빈들의 정의를 String 형식으로 가지고 있습니다. 프로그래머가 .XML 파일 혹은 Annotaion으로 정의한 빈들을 관리합니다. BeanFactory의 중요한 것은 component, configuration들을 모아서 관리를 할 수 있다는 것 입니다. 즉 properties 파일을 읽기 위해서 추가적인 객체가 필요하지 않고, 이 인터페이스가 모든 것을 할 수 있습니다. 또한 BeanFactory는 빈의 라이프사이클을 지원합니다. 이러한 라이프 사이클 지원을 위해 여러가지의 메소드들을 정의해놨습니다. 


https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/BeanFactory.html



이때 중요한 것은 BeanFactory는 빈들의 정의에 따라서 Singleton과 Prototype으로 나눌 수 있습니다. 


2. 1. Singleton scope

싱글톤은 컨테이너에 한 개의 인스턴스만 존재합니다. 자바의 static을 생각하시면 됩니다. .XML 파일기준으로 id를 이용해서 빈의 이름을 정의합니다. 하지만 동일한 이름의 빈이 여러개가 있으면 어떻게 될까요? 싱글톤은 한 개의 인스턴스만 존재하니까, 쓸 수 없는 것일까요? 혹은 많은 빈 중에 하나만 랜덤으로 실행되는 것일까요? 


아닙니다. 싱글톤에서 한 개의 인스턴스는 shared instance, 즉 공유 인스턴스입니다. 공유 쓰레드 같은 개념과 같습니다. 한 개의 인스턴스를 여러개의 빈들이 같이 사용합니다. 즉 한 개의 공유 인스턴스가 이를 사용하는 여러개의 객체, 빈으로 각각 주입됩니다. 싱글톤에서의 인스턴스는 한번 만들어지면 캐시에 저장되어 있기 때문에, 두번째 사용부터는 상당한 시간을 절약할 수 있습니다. 하지만 모든 공유자원이 마찬가지로 가지고 있는 문제점인 Thread-safe 하지 않습니다. 즉 동기화 문제가 발생할 수 있습니다. 이러한 것을 해결하는 방법은 다양하겠지만, 여기서 다루지는 않겠습니다.


이때의 Singleton scope은 Singleton pattern과 다릅니다. 싱글톤 패턴은 한 개의 클래스에 한 개의 인스턴스가 존재하는 것 입니다. 하지만 싱글톤 스콥은 한 개의 컨터이너에, 한 개의 인스턴스가 존재합니다.


싱글톤 스콥은 스프링의 default scope으로 설정되어 있습니다. 즉 별다른 설정을 하지 않으면, 기본적으로 싱글톤을 사용하게 됩니다. 


2.2. Prototype scope

프로토타입 스콥은 새로운 빈이 만들어 질 때마다, 새로운 인스턴스를 생성합니다. 한 개의 인스턴스를 공유해서 사용하는 싱글톤과 다르게 빈들이 각각의 인스턴스를 가지고 있기 때문에, 빈들이 Thread-safe 합니다. 


프로토타입에서 중요한 것이 있습니다. 빈들을 프로토타입으로 정의할 때 빈의 라이프사이클이 약간 변합니다. 빈의 라이사이클은 크게 초기화(init), 파괴(destroy) 과정이 있습니다. 하지만 스프링은 프로토타입 빈의 라이프사이클 전체를 관리하지 않습니다. 컨테이너 초기화, 빈 정의, 객체의 조립 후 바로 client(프로그래머)에게 넘겨주게 됩니다. 하지만 이때의 문제는 initialization callback은 호출 되지만, destruction callbakc은 호출되지 않습니다. 즉 컨테이너가 만들어만 주고, 안쓰는 자원을 가져가지 않습니다. 이때 사용한 프로토타입의 빈을 정리(release)하는 것은 프로그래머가 직접 다루도록 맡겨두고 있습니다. 만약에 이러한 작업을 프로그래머가 잘 해주지 않는다면, 사용하지 않는 빈들이 계속 머물면서 메모리의 자원을 사용하게 됩니다. 


2.3 Singleton bean with prototype bean

만약에 프로토타입 빈에 싱글톤 빈 1개를 주입해서 사용한다면 어떻게 될까요? 프로토타입이기 때문에 실행 때마다 다른 인스턴스가 생성될 것이지만, 결국 한 개의 빈에 주입될 것 입니다. 그래서 원래 사용하려던 빈에 아무런 영향이 없습니다.


하지만 싱글톤 빈에 프로토타입 빈을 주입한다면 어떻게 될까요? 이때는 프로토타입의 property가 변경되지 않습니다. 즉 여러개의 프로토타입 빈을 주입하더라도 인스턴스는 1개만 만들어질 것이며, 1개의 인스턴스는 여러개의 프로토타입 빈들에 주입될 것 입니다. 즉 원래의 프로토타입 빈을 사용하는 의도와 달라지게 됩니다. 



3. ApplicationContext

ApplicationContext 인터페이스는 org.springframework.context 패키지에 속하고 있습니다. 그리고 이는 BeanFactory를 구현하고 있는 인터페이스 입니다. BeanFactory를 구현하고 있는 인터페이스 답게 하는 일은 비슷하지만 좀 더 많은 기능을 구현하고 있습니다. 

 

ApplicationContext는 많은 인터페이스를 구현하고 있습니다. ApplicationEventPublisher 인터페이스를 구현하여 listener로 부터 이벤트를 발생시킬 수 있고, ResourceLoader, MessageSource(i18n 지원) 같은 기능도 구현하고 있습니다. 즉 i18n 사용을 위해서 MessageSource 인터페이스 대신에 ApplicationContext를 사용해도 상관 없습니다. 왜냐하면 MessageSource를 구현하고 있으니까요. 하지만 모든 기능에 ApplicationContext 인터페이스를 사용하게 된다면, 코드를 보는 입장에서는 명시적이지 않고 헷갈리게 될 것 입니다. 즉 명시적으로 해당 인터페이스를 직접 작성하는 것이 좋습니다.

 

스프링 공식 문서에서는 보통의 경우에는 BeanFactory 보다는 ApplicationContext 인터페이스를 사용하기를 권장하고 있습니다. 









출처

스프링부트 공식 문서





https://yeon-kr.tistory.com/125




0
  • 댓글 0

  • 로그인을 하시면 댓글 을 등록할 수 있습니다.