1.6.1 오브젝트의 동일성과 동등성
- 동일성
- 두 개의 오브젝트가 동일한(identical) 오브젝트
- == 연산자로 확인
- 사실 하나의 오브젝트만 존재하는 것이고, 두 개의 오브젝트 레퍼런스 변수를 가지고 있을 뿐임
- 동등성
- 두 개의 오브젝트가 동등한(equality) 오브젝트
- equals() 메소드로 확인
- 두 개의 각기 다른 오브젝트가 메모리상 존재
💡 스프링은 빈 요청(getBean()) 할 때다마다 동일한 오브젝트를 반환함(싱글톤)
1.6.2 싱글톤 레지스트리로서의 애플리케이션 컨텍스트
- 애플리케이션 컨텍스트는 싱글톤을 저장하고 관리하는 싱글톤 레지스트리(Singleton Registry)임
- 별다른 설정을 하지 않으면 스프링 내부에서 생성하는 빈 오브젝트는 모두 싱글톤
- 디자인 패턴에서 나오는 싱글톤과 비슷한 개념이지만 구현 방법은 확연히 다름
1.6.3 서버 애플리케이션과 싱글톤
- 스프링은 엔터프라이즈 시스템을 위해 고안된 기술
- 웹 상에서의 서블릿은 대부분 멀티스레드환경에서 싱글톤으로 동작
- 즉, 하나의 서블릿을 여러 스레드가 공유해서 사용
- 매번 새로운 오브젝트를 만들게 된다면 서버에 부하가 심해서 싱글톤으로 동작하는 것이 좋음(가비지컬렉터의 한계점도 존재)
1.6.4 싱글톤 패턴(Singleton Pattern)
- 애플리케이션 내에서 제한된 인스턴스 개수를 하나로 강제
- 하나의 인스턴스는 전역적으로 접근이 가능해야 하고, 여러 곳에 공유해야 하는 경우 주로 사용됨
- 가장 자주 활용되지만, 가장 비판을 많이 받는 패턴임
- 매우 조심해서 사용해야함
1.6.5 싱글톤을 구현하는 방법
- 생성자를 클래스 밖에서 사용하지 못하도록 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;
}
}
1.6.6 싱글톤 패턴의 한계
- private 생성자를 갖고 있기 때문에 상속을 할 수 없음
- private 생성자를 제외한 다른 생성자가 없으면 상속 불가
- 상속이 불가능 하면 객체지향적 설계의 장점을 적용하기 힘듦
- 싱글톤은 테스트하기 힘듦
- 싱글톤으로 만들어지는 방식이 제한적이기 때문에 목(Mock) 오브젝트 등으로 대체하기 힘듦
- 오브젝트를 동적으로 주입하기 힘듦
- 테스트는 엔터프라이즈 개발의 핵심
- 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못함
- 서버에서 클래스 로더를 어떻게 구성하고 있느냐에 따라서 싱글톤 클래스임에도 하나 이상의 오브젝트가 만들어 질 수 있음
- 따라서 자바 언어를 이용한 싱글톤 패턴 기법은 서버 환경에서 싱글톤이 꼭 보장되지 못함
- 여러개의 JVM에 분산돼서 설치되는 경우 각각 독립적 오브젝트가 생기기 때문에 싱글톤으로서의 가치가 떨어짐
- 싱글톤 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못함
- 싱글톤은 애플리케이션에서 전역 상태로 만들 수 밖에 없음
- 전역 상태를 갖는 것은 객체지향 프로그래밍에서는 권장되지 않음
1.6.7 싱글톤 레지스트리
- 스프링에서는 싱글톤이 만들어져 서비스 오브젝트 방식으로 사용되는 것을 적극 지지함
- 스프링에은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공하는 싱글톤 레지스트리 제공
- 스프링 컨테이너는 싱글톤으로 생성, 관리, 공급하는 싱글톤 관리 컨테이너임
- 싱글톤 레지스트리는 static 메소드와 private 생서자를 사용해야하는 비정상적인 클래스가 아니라, 평범한 자바 클래스를 싱글톤으로 활용할 수 있게 함
- 평범한 자바 클래스라도 IoC 방식의 컨테이너를 사용해서 생성과 관계설정, 사용 등에 대한 제어권을 컨테이너에게 넘겨 손쉽게 싱글톤 방식으로 만들어져서 관리되게 할 수 있음(오브젝트 생성 권한은 모두 IoC 기능을 제공하는 애플리케이션 컨텍스트에게 있기 때문)
- 싱글톤 레지스트리 덕분에 싱글톤으로 사용될 애플리케이션 클래스라도 public 생성자를 가질 수 있음
- 테스트 환경에서 자유롭게 오브젝트를 만들 수 있고, 테스트를 위한 목 오브젝트로 대체하는 것도 간단함
- 생성자 파라미터를 이용하여 사용할 오브젝트를 넣어줄 수 있게 함
- 객체지향적인 설계 방식과 싱글톤 패턴을 제외한 모든 디자인 패턴을 적용하는데 아무런 문제가 없음
- 스프링은 IoC 컨테이너 뿐만 아니라, 고전적 싱글톤 패턴을 대신해서 싱글톤을 만들고 관리하는 싱글톤 레지스트리임
1.6.8 싱글톤과 오브젝트 상태
- 싱글톤은 멀티스레드 환경이라면 여러 스레드가 동시에 접근해서 사용할 수 있음
- 따라서 상태 관리에 주의를 기울여야 함
- 서비스 형태의 오브젝트로 사용되는 경우 싱글톤은 상태정보를 갖지 않는 무상태(stateless) 방식으로 만들어져야 함(읽기 전용 이라면 상태정보를 갖고 있어도 됨)
- 여러 스레드가 동시에 싱글톤 오브젝트의 인스턴스 변수를 수정하는 것은 매우 위험
- 상태가 없는 방식으로 클래스를 만드는 경우 파라미터, 로컬 변수, 리턴 값을 활용하면 됨
- 파라미터, 로컬 변수, 리턴 값은 매번 새로운 값을 저장할 독립적인 공간이 만들어지기 때문임
1.6.9 스프링 빈의 스코프
- 스프링이 관리하는 빈의 생성, 존재, 적용되는 범위
- 보통 한 스프링 컨테이너가 존재하는 동안 계속 유지되므로 대부분 빈은 싱글톤 스코프를 가짐
- 싱글톤 스코프 이외의 스코프
- 프로토타입 스코프
- 싱글톤과 달리 컨테이너에 빈을 요청할 때마다 매번 새로운 오브젝트 생성
- 요청 스코프
- HTTP 요청이 생길 때마다 생성
- 세션 스코프
- 웹 세션의 스코프와 유사
- 프로토타입 스코프
'토비의 스프링 정리' 카테고리의 다른 글
토비의 스프링 - 1.8 XML을 이용한 설정 (0) | 2022.09.26 |
---|---|
토비의 스프링 - 1.7 의존관계 주입(DI) (0) | 2022.09.26 |
토비의 스프링 - 1.5 스프링의 IoC (0) | 2022.09.26 |
토비의 스프링 - 1.4 제어의 역전(IoC) (0) | 2022.09.26 |
토비의 스프링 - 1.3 DAO의 확장 (0) | 2022.09.26 |