Spring에서 싱글톤 패턴 적용하는 방식

jonghyun.log·2022년 6월 16일
0

spring

목록 보기
2/7
post-thumbnail

싱글톤 패턴(Singleton Pattern) 이란?

웹 애플리케이션에서 클라이언트는 보통 한명이 아닌 여러명 다수인 경우가 많다. 이 여러명의 클라이언트는
서버에 요청을 보내는데 이때, 한명씩 요청하지 않고 여러명이 '동시에' 요청하는 경우가 많다.
가령 쇼핑몰을 만들었는데 쇼핑몰의 고객이 동시에 같은 상품 정보를 요청한다고 생각해보자.

서버 모델

4명의 고객이 '동시에' 같은 후드 정보를 요청한다고 하면 웹 서버 코드는 다음과 같이 동작할 것이다.

싱글톤 미적용

상품 정보를 처리하는 객체를 생성해서 유저의 요청을 처리할 것이다.
그런데 만약, 유저가 100만명이라면 어떻게 될까?
객체를 100만개 생성해서 각각의 유저의 요청을 처리해야 할까?

단순히 생각해봐도 저런식으로 처리하면 엄청난 메모리 낭비가 일어나고 과부하가 일어난다는 것을 알 수 있다.

이런 문제를 해결하기 위해 고안한 것이 바로 싱글톤 패턴(Singleton pattern) 이다.

싱글톤 패턴(Singleton pattern) 은 로직을 처리할때 여러 객체를 만들어서 처리하는 것이 아니라 "오직 한개" 의 객체를 생성하고 그 객체를 공유해서 사용하는 패턴이다.

싱글톤 패턴을 적용하면 위의 그림은 다음과 같이 변한다.

싱글톤 적용

이런식으로 설계를 하면 불필요한 메모리 낭비를 막을 수 있다는 장점이 있다.

예시 코드

싱글톤 패턴을 만드는 가장 단순한 방법으로
클래스 생성자를 private 로 만들어서 new 로 생성하는것을 막고
static 영역에 객체를 딱 한개 생성하고 그것으로 조회하고 사용하는 방법이 있다.


 public class SingletonService {
	//1. static 영역에 객체를 딱 1개만 생성해둔다.
	private static final SingletonService instance = new SingletonService();
	//2. public으로 열어서 객체 인스터스가 필요하면 이 static 메서드를 통해서만 조회하도록 허용한다.
    public static SingletonService getInstance() {
    	return instance;
	}
	//3. 생성자를 private으로 선언해서 외부에서 new 키워드를 사용한 객체 생성을 못하게 막는다. 		
    private SingletonService() {}
}

하지만 싱글톤 패턴은 장점만이 있는 것이 아니다.

싱글톤의 문제점

1. 싱글톤을 구현하는 코드 자체가 많이들어간다.

위의 코드는 단순한 예시이지만 싱글톤을 구현하는 방법은 여러가지가 있고 
이를 모든 클래스에 적용하려면 필연적으로 부가적인 코드가 많이 필요하다.

2. 유연성이 떨어진다.

객체를 직접 생성하는 것이 아닌 호출 메서드로 가져와서 사용하므로 
유연한 의존관계 주입이 어렵고
인터페이스에 의존하지 못하고 구현 클래스에 의존해야 한다.
또한, private 로 설정해서 자식 클래스를 만들기 어럽다는 점과
내부 속성을 변경하거나 초기화 하기도 어렵기 때문에 테스트도 어렵다는 점이 있다.

스프링에서의 싱글톤

서론이 길었지만 이제 진짜 스프링에서 어떻게 싱글톤을 구현했고
어떻게 위의 문제를 해결했는지 알아보자.

스프링 빈 이라고 하는 스프링 컨테이너 가 이 역할을 해준다.

//클라이언트 코드
ApplicationContext ac = new
  AnnotationConfigApplicationContext(AppConfig.class);
//AppConfig.java
@Configuration
public class AppConfig {

    @Bean
    public GoodsService goodsService(){
        return new GoodsServiceImpl(goodsRepository());
    }

    @Bean
    public GoodsRepository goodsRepository() {
   	    return new GoodsRepository();
    }

}

이런식으로 스프링 컨테이너에 넣어주면 AnnotationConfigApplicationContext
AppConfig.class 도 스프링 빈으로 등록해주는데 그냥 등록하지 않고
AppConfig.class 를 상속받은 다른 빈으로 만들어서 AppConfig.class 안의
클래스들을 싱글톤으로 관리해주게 된다.

싱글톤으로 관리하는 주체가 우리가 아닌 스프링이므로,

  • 문제 1 해결 : 우리가 만든 클라이언트 코드에서 싱글톤을 관리하는 코드를 추가해주지 않아서 부수적인 코드 추가가 필요없다.
  • 문제 2 해결 : 스프링 컨테이너가 중간에 연결역할을 해주므로, 객체지향적으로 유연성있는 코드 작성이 가능하다.

0개의 댓글