1.6 싱글톤 레지스토리와 오브젝트 스코프
오브젝트의 동일성과 동등성 :
- 동일성(identical) :
- 동일한 오브젝트이다.
- ’==’ 연산자로 비교한다.
- 두 개의 오브젝트가 동일하다면 사실 하나의 오브젝트만 존재하는 것이고, 두 개의 다른 레퍼런스 변수를 갖고 있을 뿐이다.
- 동등성(equivalent) :
- 동일한 정보를 담고 있다.
- equals() 메소드를 이용하여 비교한다.
- 두 개의 각기 다른 오브젝트가 메모리 상에 존재하지만, 담겨져 있는 정보가 같을 때는 동등하다고 한다.
- 동일한 오브젝트는 동등하지만, 동등한 오브젝트는 동일하지 않을 수 있다.
싱글톤 레지스트리로서의 애플리케이션 컨텍스트
애플리케이션 컨텍스트는 IoC컨테이너기도 하지만, 싱즐톤을 저장하고 관리하는 싱글톤 레지스토리이기도 하다.
스프링이 주로 적용되는 대상이 자바 엔터프라이즈 기술을 사용하는 서버환경이기 때문에 싱글톤으로 빈을 관리한다.
예를 들어 요청 한 번에 10개의 오브젝트가 만들어지고, 초당 100개의 요청이 들어온다고 가정해보자. 그럼 초당 100*10 = 1000개의 오브젝트가 생성되며 1분이면 6만개, 한 시간이면 360만개의 새로운 오브젝트가 생성된다. 아무리 GC성능이 좋아졌다고 하여도 이정도 수준이면 서버가 감당하기 힘들다. 이러한 한계를 극복하기위해 애플리케이션이 구동되고 나서 부터 쭉 한 개의 오브젝트만 만들어서 사용하는 싱글톤 패턴을 사용한다.
자바에서 싱글톤을 구현하는 방법
- 클래스 밖에서는 오브젝트 생성을 못하도록 생성자를 private로 만든다.
- 생성된 싱글톤 오브젝트를 저장할 수 있는 자신과 같은 타입의 스태틱 필드를 정의한다.
- 스태틱 팩토리 메소드인 getInstance()를 만들고 이 메소드가 최초로 호출되는 시점에만 오브젝트가 만들어지도록 한다. 생성된 오브젝트는 스태틱 필드에 저장된다.
- 한 번 오브젝트가 만들어진 후에는 getInstance() 메소드를 통해 이미 만들어져 있는 오브젝트를 넘겨준다.
public class UserDao { private static UserDao INSTANCE; ... private UserDao(ConnectionMaker connectionMaker){ this.connectionMaker = connectionMaker; } public static synchronized UserDao getInstance() { if (INSTANCE == null) INSTANCE = new UserDao(???); return INSTANCE; } }
싱글톤 패턴 구현 방식의 한계
- private 생성자로 인하여 상속이 불가능하다.
- 테스트하기 어렵다.
- 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
- 서버에서 클래스 로더를 어떻게 구성하느냐에 따라 다르다.
- 여러개의 JVM에 분산되어 설치가 되는 경우에도 각각 독립적으로 오브젝트가 생길 수 있다.
- 싱글톤의 상태는 전역 상태를 만들 수 있어 바람직하지 못하다.
싱글톤 레지스트리
스프링 컨테이너에서는 위와 같이 일반 자바코드에서 작성되는 싱글톤 패턴 구현 방식의 한계를 극복하기위해 싱글톤 레지스트리를 사용한다. 싱글톤 레지스트리는 평범한 자바 클래스를 싱글톤으로 활용할 수 있게 하기 때문에 public 생성자를 가질 수 있다. 그리하여 테스트 환경에서 자유롭게 오브젝트를 만들 수 있고, 테스트를 위한 목 오브젝트로 대체하는 것도 간단하다.
싱글톤으로 만들기 때문에 주의해야 할 점은 무엇일까? 스프링은 무상태(stateless) 방식으로 만들어져야 한다. 멀티스레드 환경이라면 여러 스레드가 동시에 접근하여 서로 값을 덮어쓰고 자신이 저장하지 않은 값을 읽어올 수 있기 때문이다.
그럼 각 인스턴스별로 관리해야 하는 변수들은 어떻게 해야할까? 이 경우 파라미터와 로컬 변수, 리턴 값을 이용하면 된다. 메소드 안에 생성되는 로컬변수는 매번 새로운 값을 저장할 독립적인 공간이 만들어져 싱글톤이라 하여도 여러 스레드가 변수의 값을 덮어 쓸 일은 없다.
스프링 빈의 스코프
스프링이 관리하는 오브젝트, 즉 빈이 생성되고 존재하고 적용되는 범위를 빈의 스코프라고 한다. 스코프는 주로 아래와 같이 존재할 수 있다. 스프링 빈의 기본 스코프는 싱글톤이다.
스코프 | 설명 |
---|---|
싱글톤 스코프 | 스프링 컨테이너가 존재하는 동안 유지 |
프로토타입(prototype) 스코프 | 컨테이너에 빈을 요청할 때마다 생성 |
요청(request) 스코프 | 웹을 통해 새로운 HTTP요청이 생길 때마다 생성 |
세션(session) 스코프 | 웹을 통해 새로운 세션이 연결될 때마다 생성 |
토비의 스프링 3.1을 토대로 작성하였으나, 개인적인 의견이 담겨있어 부정확한 내용이 작성되었을 수 있습니다. 코멘트로 많은 의견 부탁드립니다 :)