1장 오브젝트와 의존관계 - 1.6 싱글톤 레지스트리와 오브젝트 스코프
1장 오브젝트와 의존관계
1.6 싱글톤 레지스트리와 오브젝트 스코프
스프링 애플리케이션 컨텍스트와 직접 만든 DaoFactory 에는 리턴되는 UserDao 에 결정적인 차이가 있다.
자바에서는 완전히 같은 동일한(identical) 오브젝트와 동일한 정보를 담고 있는(equivalent) 오브젝트는 다르다.
전자는 동일성(identity), 후자는 동등성(equality) 라고 한다.
동일성은 == 연산자로, 동등성은 equals() 메소드로 비교한다.
동일한 오브젝트는 반드시 동등하지만, 동등한 오브젝트는 반드시 동일하지 않다.
Object 의 equals() 메소드는 두 오브젝트의 동일성을 비교해서 결과를 리턴한다.
1장_ 오브젝트와 의존관계, 103.
DaoFactory 클래스의 userDao() 를 2번 호출하면 동일하지 않은 오브젝트 2개를 리턴한다.
1.6.1 싱글톤 레지스트리로서의 애플리케이션 컨텍스트
스프링의 애플리케이션 컨텍스트에 DaoFactory 를 설정정보로 등록하고 getBean() 메소드를 통해 userDao 오브젝트를 2번 호출하면 동일한 오브젝트 1개를 리턴한다.
왜냐하면 애플리케이션 컨텍스트는 싱글톤을 저장하고 관리하는 싱글톤 레지스트리 singleton registry 이기 때문이다.
애플리케이션 컨텍스트는 기본적으로 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 만든다.
싱글톤은 디자인 패턴에서 나오는 싱글톤 패턴과 비슷하지만 구현 방법은 다르다.
태생적으로 스프링은 엔터프라이즈 시스템을 위해 고안된 기술이기 때문에 싱글톤으로 빈을 만든다.
대규모 요청을 받아 처리할 수 있어야 하는 엔터프라이즈 시스템이 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만드는 방식으로는 요청을 감당하기 어렵기 때문이다.
그래서 엔터프라이즈 분야에서는 싱글톤 패턴의 원리를 이용한 서비스 오브젝트라는 개념을 만들어 단 한 개의 오브젝트만을 생성하여 사용하였다.
하지만 디자인 패턴에 소개된 싱글톤 패턴은 사용하기가 까다롭고 여러 가지 문제점이 있다.
자바에서 싱글톤 패턴을 구현하는 방법은 아래와 같다.
- 클래스 밖에서 오브젝트를 생성하지 못하도록 생성자를 private 로 만든다.
- 생성된 싱글톤 오브젝트를 저장하는 자신과 같은 타입의 스태틱 필드를 정의한다.
- 스태틱 팩토리 메소드인 getInstance() 메소드를 만들고 이 메소드가 최초로 호출되는 시점에 한번 오브젝트가 만들어지게 한다.
- 한번 오브젝트가 만들어진 후에는 getInstance() 메소드가 호출되면 이미 만들어져 있는 오브젝트를 넘겨준다.
싱글톤 패턴 구현 방식에는 다음과 같은 문제가 있다.
- private 생성자를 갖고 있기 때문에 상속할 수 없다.
- 애플리케이션의 로직을 담고 있는 일반 오브젝트가 싱글톤으로 만들어지면 상속을 사용할 수 없어 객체지향적 설계의 장점을 적용하기 어렵다.
- 테스트하기 어렵다.
- 싱글톤은 초기화 과정에서 생성자 등을 통해 사용할 오브젝트를 다이내믹하게 주입하기 힘들기 때문에 테스트용 오브젝트로 대체하기 힘들고 직접 오브젝트를 만들어야 한다.
- 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못한다.
- 여러 개의 JVM 에 분산되어 설치되는 경우에는 독립적으로 오브젝트가 생겨서 싱글톤의 가치가 떨어진다.
- 싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.
- 싱글톤의 스태틱 메소드를 이용해 전역 상태로 사용이 가능하고, 전역 상태는 객체지향 프로그래밍에서 권장되지 앟는 프로그래밍 방식이다.
싱글톤 패턴의 구현 방식은 위와 같은 여러가지 단점이 있다.
그래서 스프링에서는 싱글톤 형태의 오브젝트를 만들고 관리하는 기능인 싱글톤 레지스트리 singleton registry 를 제공한다.
싱글톤 레지스트리는 평범한 자바 클래스를 싱글톤으로 활용할 수 있게 해준다.
따라서 public 생성자를 가질 수 있고, 만약 싱글톤이 필요하지 않는 환경이라면 간단히 오브젝트를 생성해서 사용할 수도 있다.
따라서 UserDao 는 스프링 IoC 를 적용하면서 싱글톤으로 만들어 진다.
싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있기 때문에 상태 관리에 상당히 주의를 기울여야 한다.
1.6.2 싱글톤과 오브젝트의 상태
기본적으로 멀티스레드 환경에서 서비스 형태의 오브젝트로 사용되는 경우, 무상태 stateless 방식으로 만들어져야 한다.
싱글톤 안의 메소드 파라미터나 메소드 안에서 생성되는 로컬 변수는 매번 새로운 값을 저장할 독립적인 공간으로 만들어진다.
그렇기 때문에 멀티스레드 환경에서도 변수의 값을 덮어쓸 일은 없다.
단순히 읽기전용 정보라면 싱글톤에서 인스턴스 변수로 사용해도 좋다.
이 경우 static final 이나 final 로 선언한다.
1.6.3 스프링 빈의 스코프
스프링이 관리하는 빈의 생성, 관리, 적용되는 범위인 빈 스코프 bean scope 개념이 있다.
기본 스코프는 싱글톤이다.
싱글톤 singleton 스코프는 컨테이너 내에 한 개의 오브젝트만 생성한다.
프로토타입 prototype 스코프는 컨테이너에 빈을 요청할 때마다 매번 새로운 오브젝트를 생성한다.
요청 request 스코프는 웹을 통해 새로운 http 요청이 생갈 때마다 새로운 오브텍트를 생성한다.