싱글톤 패턴


서블릿의 개수가 너무 많아 생성되는 객체들 또한 너무 많다.
어떻게 해결할 수 있을까?

위에서 서블릿 하나당 Service 객체가 만들어지고 이어서 똑같은 Repository 객체가 각각 3개씩 만들어진다. 이는 메모리 효율의 낭비를 야기한다. 어떻게 해결할 수 있을까?

  1. 서블릿을 하나로 묶는다.
  2. 싱글톤패턴으로 Service와 Repository 객체를 각각 하나씩 생성한다.

우리는 싱글톤패턴으로 이 문제를 해결해보도록 한다.

public class CustomerService {
	private CustomerRepository repository;
	public CustomerService() {
		repository = new CustomerRepository();
	}

CustomerService를 예를 들어보도록하자.
위 코드를 보면 외부에서 CustomerService 객체를 마음대로 생성할 수 있다. 우린 이 서비스 객체가 하나씩만 생성되길 원한다.

이 때, 싱글톤 패턴의 핵심은 생성자를 private로 접근제한해서 외부에서 new연산자로 생성자를 호출할 수 없도록 막는 것이다.

public class CustomerService {
	private CustomerRepository repository;
	private CustomerService() {
		repository = new CustomerRepository();
	}

public을 private로 바꿨으니 외부에선 생성자를 이제 호출할 수 없다.

public class CustomerService {
	private static CustomerService service = new CustomerService();
	private CustomerRepository repository;
	
	private CustomerService() {
		repository = new CustomerRepository();
	}
	public static CustomerService getInstance() {
		return service;
	}

private static은 자바에서 사용하는 두 개의 접근 지시자를 함께 사용한 것입니다.

  1. private: 이 접근 지시자는 해당 필드나 메서드가 선언된 클래스 내부에서만 접근 가능함을 나타냅니다. 다른 클래스에서는 접근할 수 없습니다.

  2. static: 이 키워드는 해당 필드가 클래스 레벨의 필드임을 나타냅니다. 즉, 이 필드는 클래스의 모든 인스턴스에서 공유되며 클래스가 메모리에 로드될 때 한 번만 생성됩니다.

따라서, private static CustomerService service = new CustomerService(); 구문은 CustomerService 클래스의 인스턴스를 생성하고, 이를 클래스 레벨에서 공유되는 service라는 필드에 할당하며, 이 필드는 CustomerService 클래스 내부에서만 접근 가능하다는 것을 의미합니다.

이렇게 생성된 service 객체는 JVM(Java Virtual Machine)의 메소드 영역에 저장됩니다. JVM의 메모리는 크게 힙 영역, 스택 영역, 메소드 영역으로 나뉩니다. 여기서 스태틱 변수는 메소드 영역에 저장되며, 프로그램이 시작될 때 생성되고 종료될 때 파괴됩니다. 즉, service는 프로그램이 실행되는 동안에 계속 유지되며, 같은 클래스의 모든 인스턴스에서 공유됩니다.

이 코드는 싱글턴 패턴의 한 예입니다. 이 패턴을 사용하면, CustomerService 클래스의 인스턴스는 프로그램 내에서 단 한 번만 생성되고, 이후에는 getInstance() 메소드를 통해 이 인스턴스에 접근할 수 있습니다. 이 방식을 통해 리소스를 절약하고, 모든 곳에서 동일한 CustomerService 인스턴스를 사용할 수 있습니다.


@WebServlet("/loginservlet")
public class LoginServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	private CustomerService service;
	public LoginServlet() {
		//service = new CustomerService();
		service = CustomerService.getInstance();
	}

그리고 나서 위와 같이 서블릿 부분에서는 new로 생성자를 호출하는 것이 아닌 service = CustomerService.getInstance();을 이용해 호출한다.

이제 위와 같이 각각의 서블릿들이 하나의 CustomerService를 이용하게 된다.

그럼 Repository도 싱글톤패턴으로 또 만들어야해?

위의 그림에서 보면 알 수 있듯이 어차피 서비스객체가 싱글톤패턴으로 하나만 만들어지므로 자연스레 레파지토리 객체를 한번만 호출하게 된다. 따라서 따로 만들필요는 없다.


위 사진은 하나의 서블릿을 이용하는 예인데, 아직 내가 모르는 부분이므로 다음에 정리하도록한다.

0개의 댓글