목차

    싱글턴 패턴(Singleton pattern)

    소프트웨어 디자인 패턴에서 싱글턴 패턴을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다.

    싱글턴 패턴을 사용하는 이유

    만약 우리가 만들었던 DI 컨테이너인 요청을 할 때마다 새로운 객체를 생성한다. 요청이 엄청나게 많은 트래픽 사이트에서는 계속 객체를 생성하게 되면 메모리 낭비가 심하기 때문이다.

    스프링 컨테이너

    스프링 컨테이너는 싱글턴 패턴을 적용하지 않아도 객체 인스턴스를 싱글톤으로 관리한다. 이러한 기능 덕분에 싱글톤 패턴의 모든 단점을 해결하고 객체를 싱글톤으로 유지할 수 있다

    Spring에서 싱글톤을 사용하는 이유

    애플리케이션 컨텍스트에 의해 등록된 빈은 기본적으로 싱글톤으로 관리된다. 즉, 스프링에 여러 번 빈을 요청하더라도 매번 동일한 객체를 돌려준다는 것이다. 애플리케이션 컨텍스트가 싱글톤으로 빈을 관리하는 이유는 대규모 트래픽을 처리할 수 있도록 하기 위함이다.

    스프링은 최초에 설계될 때 부터 대규모의 엔터프라이즈 환경에서 요청을 처리할 수 있도록 고안되었다. 그리고 그에 따라 계층적으로 처리 구조(Controller, Service, Repository 등) 가 나뉘어지게 되었다.

    그런데 매번 클라이언트에서 요청이 올 때마다 각 로직을 처리하는 빈을 새로 만들어서 사용한다고 생각해보자. 요청 1번에 5개의 객체가 만들어진다고 하고, 1초에 500번 요청이 온다고 하면 초당 2500개의 새로운 객체가 생성된다. 아무리 GC의 성능이 좋아졌다 하더라도 부하가 걸리면 감당이 힘들 것이다.

    그래서 이러한 문제를 해결하고자 빈을 싱글톤 스코프로 관리하여 1개의 요청이 왔을 때 여러 쓰레드가 빈을 공유해 처리하도록 하였다.

     Spring에서 관리하는 싱글톤의 장점

    Java로 기본적인 싱글톤 패턴을 구현하고자 하면 다음과 같은 단점들이 발생한다.

    • private 생성자를 갖고 있어 상속이 불가능하다.
    • 싱글톤으로 생성되면 객체테스트가 어렵기 때문에, 테스트를 위한 객체를 새로만들어야한다.
    • 서버 환경에서는 싱글톤이 1개만 생성됨을 보장하지 못한다.
    • 전역 상태를 만들 수 있기 때문에 바람직하지 못하다.

    기본적으로 싱글톤이 멀티쓰레드 환경에서 서비스 형태의 객체로 사용되기 위해서는 내부에 상태정보를 갖지 않는 무상태(Stateless) 방식으로 만들어져야 한다. 만약 여러 쓰레드들이 동시에 상태를 접근하여 수정한다면 상당히 위험하기 때문이다.

    직접 싱글톤을 구현한다면 상당히 많은 단점들이 있겠지만, Spring 프레임워크에서 직접 싱글톤으로 객체를 관리해주므로, 우리는 더욱 객체지향적인 개발을 할 수 있게 된 것이다.

    싱글턴 방식의 주의점 ✨

    싱글톤 패턴이든, 스프링에서 객체 인스턴스를 하나만 생성해서 공유하는 상황에서 객체 인스턴스를 공유하기 때문에 객체 상태를 유지(stateful)하게 설계하면 안된다.
    1. price는 공유되는 필드이기 때문에 특정 클라이언트가 값을 변경한다.
    2. 실무에서 이런 경우를 종종 보는데, 이로인해 정말 해결하기 어려운 큰 문제들이 터진다.(몇년에 한번씩 꼭 만난다.)

    stateless(무상태)방식으로 만들어라.

    • 읽기전용 값이라면 초기화시점에서 iv에 저장해두고 공유하는 것은 문제가 없지만,
      다중 사용자의 요청을 한꺼번에 처리하는 쓰레드들이 동시에 iv를 건드리는 것은 위험하다. 따라서 stateless방식으로 만들어져야한다.
    • 파라미터, 로컬변수, 리턴값 등을 이용해, 각각의 값을 iv처럼 공유되는 영역이 아닌, 독립적인 영역에 저장하자.

    싱글톤 레지스트리

    그래서 스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공하는데, 그것이 바로 싱글톤 레지스트리(Singleton Registry) 이다. 스프링 컨테이너는 싱글톤을 생성하고, 관리하고 공급하는 컨테이너이기도 하다. 싱글톤 레지스트리의 장점은 다음과 같다.

    • static 메소드나 private 생성자 등을 사용하지 않아 객체지향적 개발을 할 수 있다.
    • 테스트를 하기 편리하다.

    이러한 스프링에 장점을 활용하여 초기에 설정하면 사용중에는 변하지않는 읽기전용 인스턴스 변수인경우에는 서버의 성능향상을 위해 bean으로 등록하고 사용하자. 

    'Java > *****디자인패턴' 카테고리의 다른 글

    퍼사드(Facade) 패턴  (0) 2022.04.03
    빌더 패턴  (0) 2022.04.01
    싱글톤 (Singleton) 패턴  (0) 2022.04.01
    디자인 패턴  (0) 2022.03.31
    디자인 패턴 싱글톤 패턴 개념 정리  (0) 2022.03.18

    + Recent posts