티스토리 뷰

spring

싱글톤 패턴

kirinman 2022. 12. 30. 13:48

왜 싱글톤 패턴을 사용해야 하는가.

스프링은 기본적으로 기업용 온라인 서비스를 지원하기 위해 만들어졌다.

 

이런 웹 어플리케이션은 보통 여러 고객들이 동시에 요청을 하게 될 것이다.

 

이런 상황에서 내가 그냥 순수한 DI 컨테이너를 사용하게 된다면

고객들이 요청을 할때마다, 즉 호출할 때 마다 새로운 객체를 생성하게 될 것이다.

 

만일 초당 5만 건 정도의 요청이 동시에 들어오게 된다고 하면 그만큼의 객체를 생성하게 되는 것이다.

이것은 메모리 낭비가 너무 심한 일이다.

 

하기 테스트코드를 통해서 요청이 들어올 때 마다 새로운 객체가 생성되는 것을 확인할 수 있다.

public class SingletoneTest {

    @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);

    }
}

 

이러한 문제를 해결하기 위해 해당 객체가 딱 1개만 생성되고, 공유하도록 설계하는 싱글톤 패턴이 등장한다.

 

싱글톤 패턴을 적용한 코드!

package JustJava.singletone;

public class SingletoneService {
    private static final SingletoneService instance = new SingletoneService();

    public static SingletoneService getInstance() {
        return instance;
    }

    private SingletoneService() {

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

1.먼저 static 영역에 객체 instance를 하나 생성해서 올려둔다.

  첫 줄을 보면 SingletonService라는 클래스가 자기 자신을 생성해서 instance 객체 안에 숨어있는 것을 확인할 수 있다.

 

2.이 객체는 오직 getInstance를 통해서만 호출할 수 있다. 이것은 항상 같은 인스턴스를 반환한다.

 

3.딱 1개의 인스턴스만 존재해야 하니 생성자를 private으로 막아서 외부에서 객체 인스턴스가 생성되는 것을 막는다.

 

이렇게 하면 다른 사람들이 이걸 보면 생성자 private? 아 이거 싱글톤이구나

그럼 이거 어떻게 꺼내지?

이렇게 생각할 것이다.

 

만약 public이라면?

다른 사람들이 오예~ 그냥 객체 5천만개 생성해서 내 맘대로 써버려야지~

이렇게 될 수도 있다.

 

하지만 이렇게만 사용하게 된다면 DIP, OCP도 위반하고, 자식 클래스도 만들 수 없다.

 

이런 문제를 해결한 것이 스프링 컨테이너!(싱글톤 컨테이너라고도 한다.)

'spring' 카테고리의 다른 글

DI  (0) 2022.12.30
IoC (Spring에 국한된 것 아님!)  (0) 2022.12.30
@Entity / @Table  (0) 2022.12.30
@Enumerated  (0) 2022.12.30
primitive type으로 안하는 이유?  (0) 2022.12.28
댓글