티스토리 뷰

Spring

[Spring] Spring Singleton(싱글톤)

Gray__ 2022. 1. 17. 22:11

싱글톤 패턴 개념에 들어가기 전, 한 웹사이트에 동시에 50000명의 고객이 접속한다고 하자.

앞서 빈 객체에 관해 공부를 했다. 동시에 5만명의 고객이 접속한다고 하면 50000만개의 객체를 동시에 생성해야될까?

 

Configuration 1개가 1개 이상의 객체를 생성할 가능성이 높은데 객체가 최소한 1개씩만 있다고 하더라도 50000개의 객체를 동시에 만들어야 한다. 이것이 가능할까?

 

스프링이 없는 순수 자바코드를 이용해 빈 설정 정보를 확인하는 테스트 코드를 작성하였다

package hello.core_review.singleton;

import hello.core_review.AppConfig;
import hello.core_review.member.MemberService;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class SingletonTest {

    @Test
    @DisplayName("스프링 없는 순수한 DI 컨테이너")
    void pureContainer(){
        AppConfig appConfig = new AppConfig();
        // 1. 조회: 호출할 때 마다 객체를 생성하는지
        MemberService memberService1 = appConfig.memberService();

        // 2. 조회: 호출할 때 마다 객체를 생성하는지
        MemberService memberService2 = appConfig.memberService();

        // 참조값이 다른 것을 확인
        System.out.println("memberService1 = " + memberService1);
        System.out.println("memberService2 = " + memberService2);

        // memberService1 != memberService2
        Assertions.assertThat(memberService1).isNotSameAs(memberService2);
    }

}

테스트를 실행한 결과를 보면 MemberService 객체 하나당 서로 다른 객체가 할당되는 것을 볼 수 있다.

만약 50000명이 동시에 접속한다고 하면 50000개의 객체를 동시에 생성해야된다.

이렇게 되면 서버에 엄청난 과부하가 발생될 것이다.


싱글톤 패턴

  • 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
  • 객체 인스턴스를 2개 이상 생성하지 못하도록 Private 생성자로 막아야 한다.

 

instance를 private static으로 선언하고 해당 클래스의 생성자를 private으로 선언한다.

객체의 instance를 얻기 위해서는 반드시 getInstance 함수를 이용해야 한다.

package hello.core_review.singleton;

public class SingletonService {

    private static final SingletonService instance = new SingletonService();

    public static SingletonService getInstance(){
        return instance;
    }

    private SingletonService(){
    }

    public void logic(){
        System.out.println("싱글톤 객체 로직 호출");
    }
}

 

싱글톤 패턴을 적용하면 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있다. 

 

그러나 싱글톤 패턴은 몇 가지의 문제점을 가지고 있다.

 

1. 코드가 길다
2. 클라이언트가 구체 클래스에 의존
3. DIP를 위반하고 OCP도 위반할 가능성이 높다
4. 테스트하기 어렵다
5. 내부 속성을 변경하거나 초기화 하기 어려움
6. 자식 클래스를 만들기 어려움
7. 결론적으로 유연성이 떨어진다

 

이러한 문제점을 한번에 해결해주는 것이 스프링 컨테이너이다.

스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서 객체 인스턴스를 싱글톤으로 관리한다

스프링 컨테이너가 관리하는 싱글톤 패턴

 

스프링 컨테이너를 이용한 싱글톤 패턴이든, 자바코드로 구현한 싱글톤 패턴이든 반드시 주의할 점이 있다.

 

싱글톤 패턴은 객체 인스턴스를 하나만 생성해서 공유하는 개념이다.

 

예를 들어 A 고객이 10000원치 주문을 하고, B 고객이 20000원치 주문을 했다고 하자.

 

B 고객이 주문을 완료하고 난 후, A 고객이 자신의 주문 금액을 확인하면 어떻게 될까?

 

A 고객, B 고객 둘 다 동일한 객체에 접근하기 때문에 A 고객은 20000원 이라는 가격을 받아보게 된다.

 

그러므로 반드시 싱글톤 객체는 상태를 유지(Stateful)하도록 설계하면 안된다

 

무상태(Stateless)로 설계해야 한다.

 

- 특정 클라이언트에 의존적인 필드가 있으면 안된다.

- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.

- 가급적 읽기만 가능해야 하고, 필드 대신에 공유되지 않는 지역변수, 파라미터를 사용해야 한다

댓글