[Spring] 싱글톤 레지스트리와 오브젝트 스코프

Zoe·2022년 1월 7일
0

Spring

목록 보기
3/9
post-thumbnail

싱글톤 레지스트리와 오브젝트 스코프


✅ 애플리케이션 컨텍스트와 오브젝트 팩토리의 차이점

DaoFactory의 userDao() 메소드를 두 번 호출해서 리턴되는 UserDao 오브젝트

//직접 생성한 DaoFactory 오브젝트 출력코드
DaoFactory factory = new DaoFactory();
UserDao dao1 = factory.userDao();
UserDao dao2 = factory.userDao();

System.out.println(dao1);
System.out.println(dao2);

💻 출력 :

springbook.dao.Userdao@118f375
springbook.dao.Userdao@117a8bd

  • 다른 값을 가진 동일하지 않은 오브젝트가 두 개 생김
  • userDao를 매번 호출하면 계속해서 새로운 오브젝트가 만들어질 것
ApplicationContext context = new AnnotationConfigApplicationContext(DaoFactory.class);

UserDao dao3 = context.getBean("userDao", UserDao.class);
UserDao dao4 = context.getBean("userDao", UserDao.class);

System.out.println(dao3);
System.out.println(dao4);

💻 출력 :

springbook.dao.UserDao@ee22f7
springbook.dao.UserDao@ee22f7

  • getBean()을 두 번 호출해서 가져온 오브젝트가 동일함
  • 스프링은 여러 번에 걸쳐 빈을 요청하더라도 매번 동일한 오브젝트를 돌려준다는 것

✅ 싱글톤 레지스트리로서의 애플리케이션 컨텍스트

🌟 싱글톤 레지스트리 : 싱글톤을 저장하고 관리
🌟 스프링은 기본적으로 별다른 설정을 하지 않으면 내부에서 생성하는 빈 오브젝트를 모두 싱글톤으로 생성

1️⃣ 서버 애플리케이션과 싱글톤

  • 왜 스프링은 싱글톤으로 을 만들까?
    스프링은 대부분 서버 환경에서 사용됨. 스프링이 처음 설계됐던 대규모의 엔터프라이즈 서버환경은 서버 하나당 최대로 초당 수십에서 수백 번씩 브라우저나 여타 시스템으로부터의 요청을 받아 처리할 수 있는 높은 성능이 요구되는 환경이었음. 그런데 매번 클라이언트에서 요청이 올 때마다 각 로직을 담당하는 오브젝트를 새로 만들어서 사용한다고 생각해보자. 요청 한 번에 5개의 오브젝트가 새로 만들어지고 초당 500개의 요청이 들어오면, 초당 2500개의 새로운 오브젝트가 생성됨. 1분이면 십오만 개, 한 시간이면 9백만 개의 새로운 오브젝트가 만들어짐. 아무리 자바의 오브젝트 생성과 가비지 컬렉션의 성능이 좋아졌다고 해도 이렇게 부하가 걸리면 서버가 감당하기 힘듬. 그래서 서비스 오브젝트 생김. 서블릿은 대부분 멀티스레드 환경에서 싱글톤으로 동작
  • 싱글톤 패턴의 원리 : 한 개의 오브젝트만 만들어서 사용하는 것, 서버환경에서는 서비스 싱글톤의 사용이 권장됨.

  • 안티패턴이라고 하는 개발자도 존재 : 사용하기 까다롭고 문제점이 많기 때문에

2️⃣ 싱글톤 패턴의 한계

자바에서 싱글톤을 구현하는 방법

  • 클래스 밖에서는 오브젝트를 생성하지 못하도록 생성자를 private로 만듦
  • 생성된 싱글톤 오브젝트를 저장할 수 있는 자신과 같은 타입의 static field를 정의
  • static factory methodgetInstance()를 만들고 이 메소드가 최초로 호출되는 시점에서 한 번만 오브젝트가 만들어지게 함. 생성된 오브젝트는 static field에 저장됨. 또는 static field의 초기값으로 오브젝트를 미리 만들어둘 수도 있음.
  • 한번 오브젝트(싱글톤)가 만들어지고 난 후에는 getInstance() 메소드를 통해 이미 만들어져 static field에 저장해둔 오브젝트를 넘겨줌.
//싱글톤 패턴을 적용한 UserDao
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 생성자를 갖고 있기 때문에 상속할 수 없음
  • 싱글톤은 테스트하기가 어려움
  • 서버환경에서는 싱글톤이 하나만 만들어지는 것을 보장하지 못함
  • 싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직하지 못함

3️⃣ 싱글톤 레지스트리

🌟 싱글톤 레지스트리 : 스프링이 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능, 스프링이 지지하는 객체지향적인 설계 방식과 원칙, 디자인 패턴 등을 적용하는 데 아무런 제약이 없음.

✅ 싱글톤과 오브젝트의 상태

//인스턴스 변수를 사용하도록 수정한 UserDao
public class UserDao {
	 private ConnectionMaker connectionMaker;//초기에 설정하면 사용 중에는 바뀌지 않는 읽기 전용 인스턴스 변수
     private Connection c;//매번 새로운 값으로 바뀌는 정보를 담은 인스턴스 변수. 심각한 문제가 발생한다.
     private User user;// 위와 동일
     
     public User get(String id) throws ClassNotFoundException, SQLException {
     	this.c = connectionMaker.makeConnection();
        ...
		this.user = new User();
        this.user.setId(rs.getString("id"));
        this.user.setName(rs.getString("name"));
        this.user.setPassword(rs.getString("password"));
        ...
        return this.user;
     }
 }  
  • Connection 과 User를 클래스의 인스턴스 필드로 선언.

  • 싱글톤으로 만들어져서 멀티스레드 환경에서 사용하면 심각한 문제가 발생.

✅ 스프링 빈의 스코프

  • 스프링 빈의 기본 스코프는 싱글톤
  • 싱글톤 외의 스코프를 가질 수 있음.
  • 프로토타입 스코프 : 컨테이너에 빈을 요청할 때마다 매번 새로운 오브젝트를 생성
  • 요청 스코프
  • 세션 스코프
profile
iOS 개발자😺

0개의 댓글