[Spring] Singleton 패턴 : 인스턴스 아나바다 운동

2025. 6. 16. 17:43·Spring/Core

싱글톤 패턴

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

대표적인 방법으로는 private 생성자를 사용하여 외부에서 호출할 수 없도록 하는 방법이 있다.

public class SingletonService {

    // 1. static 영역에 딱 하나만 미리 생성
    private static final SingletonService instance = new SingletonService();

    // 2. public 으로 열어서 객체 인스턴스가 필요하면 조회가 가능하도록 static 허용
    public static SingletonService getInstance() {
        System.out.println(instance);
        return instance;
    }

    // 3. 생성자를 private 으로 만들서어 외부에서 생성 금지
    private SingletonService() {
    }

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

생성자는 private으로 막은뒤, static 영역 (클래스 레벨) 에 객체를 미리 하나 만들어두고, 해당 객체를 조회해서 사용하는 방법을 사용하면 된다. 

이때 이 인스턴스는 클래스 레벨에 단 하나만 존재하므로 코드 어디서든 이 인스턴스를 호출하면 같은 인스턴스를 반환 받는다.

-> 즉 우리는 하나의 객체를 공유하며 효율적으로 사용할 수 있다.

 

싱글톤의 문제점

싱글톤은 효율적으로만 보일 수도 있지만, 클래스 레벨에 생성하고 생성자를 막는 등 바이트 코드 자체가 많이 들어가고, 인스턴스가 구체 클래스에 의존하게 되어 DIP를 위반하게 된다.

또한 해당 instance 의 구현체로 다른 것을 넣으려면 클라이언트 코드를 수정해야하는 OCP 원칙이 위배 될 수도 있고, 속성 변경 어려움, 확정성 저하 등 유연성이 떨어진다는 단점이 있어 안티 패턴 이라고도 불린다.

 


Singleton 컨테이너

스프링 컨테이너는 이러한 문제점을 해결하면서도 객체를 하나만 생성하여 관리한다. 스프링 빈이 바로 컨테이너 내부에서 싱글톤으로 관리되는 빈이다.

스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도 알 ! 아 ! 서 ! 관리 해준다 -> 개발자는 그냥 신경 안쓰고 개발해도 됨. -> 참고로 이를 싱글톤 레지스트리 라고 한다

덕분에 우리는 지저분한 바이트코드를 줄이고, DIP, OCP 등을 준수하며 자유롭게 싱글톤을 적용할 수 있다.

 

그까짓꺼 테스트 코드로 검증해봅시다

이참에 테스트 코드도 작성해보자.

@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer() {

	ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); // 스프링 컨테이너는 싱글톤을 자동으로 관리

	// 1. 조회 : 호출할 때마다 같은 객체를 반환
	MemberService memberService1 = ac.getBean("memberService", MemberService.class);

	// 2. 조회 : 호출할 때마다 같은 객체를 반환
	MemberService memberService2 = ac.getBean("memberService", MemberService.class);

	System.out.println("memberService1 = " + memberService1);
	System.out.println("memberService2 = " + memberService2);

	try {
            assertThat(memberService1).isSameAs(memberService2);
            System.out.println("같은 객체가 맞습니다 !");
        } catch (Exception e) {
            System.out.println("같은 객체가 아닙니다..");
        }
}

정상적으로 테스트가 통과한것을 볼 수 있다.

 


싱글톤 방식 주의점

비단 싱글톤 패턴 뿐만 아니라, 하나의 객체를 여러 클라이언트가 공유하는 상황이라면, 상태를 유지(stateful) 하게 설계하면 안된다.

반드시 반드시 반드시 무상태 (stateless) 하게 설계해야한다 !

즉, 특정 클라이언트에게 의존적인 필드가 존재하면 안되고, 특정 클라이언트가 값을 변경할 수 있는 필드가 존재하면 안된다.

예를 들면 다음과 같은 코드가 있다고 가정하자(멀티스레드 상황 X).

public class StatefulService {

    private int price;

    public void order(String name, int price) {
        System.out.println("name = " + name + " price = " + price);
        this.price = price; // 여기서 문제 발생

    }

    public int getPrice() {
        return price;
    }
}

위 코드는 price라는 값이 상태를 유지 하며 객체가 공유가 된다.

즉 A라는 사용자의 결제 내용이 B라는 사용자의 결제 내용에 의해 덮어씌워질 수 있게 된다.

이럴 때는 다음과 같이 리팩토링을 고려하자.

public class StatelessService {

    public int order(String name, int price) {
        System.out.println("name = " + name + " price = " + price);
        // 내부에 값을 저장하지 않고, 바로 결과를 반환
        return price;
    }
}

공유 변수를 삭제하고, 메서드의 반환 값을 즉시 반환하도록 하여 상태를 stateless하게 리팩토링 했다.

특히 멀티스레드와 함께 금전적인 문제가 발생하게 되면 정말 크고 머리 아픈 문제가 발생하게 되므로 항상 조심하자!

'Spring > Core' 카테고리의 다른 글

[Spring] Dependency Injection : 의존 관계 주입의 4가지 방법  (0) 2025.06.19
[Spring] @ComponentScan , @AutoWired - 자동 Bean 등록  (0) 2025.06.16
[Spring] 스프링 컨테이너 - ApplicationContext, Bean 조회  (0) 2025.06.16
[Spring] BeanFactory와 ApplicationContext  (0) 2025.05.25
[Spring] @PostConstruct, @PreDestroy 와 컴포넌트 스캔의 궁합  (0) 2025.05.19
'Spring/Core' 카테고리의 다른 글
  • [Spring] Dependency Injection : 의존 관계 주입의 4가지 방법
  • [Spring] @ComponentScan , @AutoWired - 자동 Bean 등록
  • [Spring] 스프링 컨테이너 - ApplicationContext, Bean 조회
  • [Spring] BeanFactory와 ApplicationContext
xuv2
xuv2
집에 가고 싶다
  • xuv2
    xuvlog
    xuv2
  • 전체
    오늘
    어제
    • 전체 글 모아보기 (173) N
      • 잡담 (9)
      • 도전 , 자격증 (2)
      • Error (6) N
      • Java (23)
      • Spring (40)
        • Core (10)
        • MVC (21)
        • Thymeleaf (9)
      • DataBase (6)
        • Database Modeling (4)
        • SQL (2)
      • HTTP (11)
      • Network (17)
      • Software Engineering (3)
      • Operating System (3)
      • Algorithm (16)
      • Project (19)
        • Web (9)
        • iOS (8)
        • Python (1)
        • Toy Project (1)
      • A.I (13)
      • Linux (5)
  • 블로그 메뉴

    • 홈
  • 링크

    • Github
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
xuv2
[Spring] Singleton 패턴 : 인스턴스 아나바다 운동
상단으로

티스토리툴바