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을 토대로 작성하였으나, 개인적인 의견이 담겨있어 부정확한 내용이 작성되었을 수 있습니다. 코멘트로 많은 의견 부탁드립니다 :)


oksusutea's blog

꾸준히 기록하려고 만든 블로그