본문 바로가기

연재작/WEB - BE

Spring bean (2) - Singleton, Bean

 

1. 싱글턴 패턴.

 

싱글턴 패턴이란? 하나의 클래스에 대해 오직 하나의 인스턴스만 생성되도록 보장하는 디자인 패턴이다.

그리고 이를 이용해서 전역적인 관리를 하기 위해 사용한다.

 

주요 특징 : 

  • 하나의 인스턴스: 클래스에 대해 단 하나의 인스턴스만 존재,
    필요시 인스턴스를 생성하거나 기존 인스턴스를 반환
  • 글로벌 접근: 싱글톤 객체는 어디서든 접근 가능
  • 메모리 효율성: 불필요한 객체 생성을 막아 메모리와 자원을 절약

 

가령 MVC 패턴을 사용한다고 할 때, Controller에서 사용되는 View와 같은 인스턴스는

재생성 될 필요가 없고, 이를 어플리케이션이 끝날 때 까지 사용해야 한다.

이럴 경우 View를 싱글턴을 사용해서 관리 할 수 있다.

 

인스턴스가 단 한 개만 존재하기 위해서 클래스를 작성할 때 아래와 같은 내용이 만족되어야한다.

  • static으로 field를 통해 유일성을 만족시켜야한다.
  • private 생성자를 통해서 외부에서 생성하지 못하도록 설정해야 한다.
  • static 메서드를 통해 유일한 field인 인스턴스를 생성 or 재사용 할 수 있게 반환되어야 한다.

예시를 들면 아래와 같다.

public class Singleton {
	private static Singleton singletonInstance; // 유일한 singleton instance 정의
    
    private Singleton() {}; // private 선언을 통해 생성이 되지 않도록 설정
    
    public static Singleton getInstance() {
    	if (this.singletoneInstance == null) {
        	singletoneInstance = new Singleton()
        }
        return singletonInstance;
    }; // 인스턴스가 없을 경우 유일한 싱글턴 객체를 생성
    // 있다면 해당 인스턴스를 반환.
}

 

 

+) 싱글톤이 부적합한 경우

싱글톤 스코프에서는 여러 사용자가 동일한 인스턴스를 공유한다. 

사용자별로 다른 데이터를 다루는 객체는 싱글톤으로 사용하기에 적합하지 않다.

예를 들어, 사용자가 로그인할 때마다 로그인 정보를 전역적으로 공유하는 것은 보안 문제를 일으킬 수 있다.

  • 개인화된 데이터: 각 사용자별로 고유한 데이터를 다루어야 하는 경우 (예: 로그인 세션, 사용자 설정, 장바구니 데이터 등).
  • 요청별로 다른 데이터: 사용자의 요청에 따라 데이터가 달라지는 경우 (예: 폼 입력값, 검색 결과 등).

 

2. bean은 싱글턴인가 아닌가

 

싱글턴에 대해 공부하던 중 Spring bean 이 싱글턴인지 테스트해보기 위해서 다음과 같이 Controller의 코드를 짰고,

@Slf4j
@RestController
@RequestMapping("/members")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class MemberController {
    MemberService memberService;
    MemberService memberService2;

    @GetMapping("/{id}")
    public ResponseEntity<MemberResponseDto> read(@PathVariable Integer id) {
        MemberResponseDto responseDto = memberService2.read(id);
        return ResponseEntity.ok(responseDto);
    }

Service코드에는 lombok을 통한 생성자만을 넣었을 뿐 싱글턴으로 사용하기 위한 제약을 걸어두지 않았다.

@Getter
@Service
@RequiredArgsConstructor
@FieldDefaults(makeFinal= true, level= AccessLevel.PRIVATE)
public class MemberService {
    private final MemberRepository memberRepository;

 

이렇게 해도 실행이 되었다. spring bean은 싱글턴으로 사용된다고 들었는데,

왜 이렇게 설정해두어도 사용이 가능한 것일까?

com.example.member.service.MemberService@c7cd8fb
com.example.member.service.MemberService@c7cd8fb

 

그래서 memberService, memberService2 두 개의 정보를 출력해보니 위 처럼 두 개가 같은 참조값이 나왔다.

memberService == memberService2 또한 true로 나왔다.

 

즉, Spring에서는 굳이 싱글턴을 설정하지 않아도

@controller, @Service, @Repository등의 annotation을 통해 bean으로 설정 한다면

memberService, memberService2와 같이 서로 다른 변수로 선언한다고 하더라도

생성자를 통해 주입 할 때는 싱글턴 패턴으로 사용 하도록 단일 객체만을 주입해서 싱글톤으로 관리하는 것이다.

다시 말해, 동일한 싱글턴 Bean 인스턴스를 주입 받는 것이다.

 

 

다음 글 예고) 다시 정리하는 Spring에서 Bean이란

Spring IoC 컨테이너에서 관리하는 Java객체이다.

Java의 객체(POJO : Plain Old Java Object ➡️ 오래된 방식의 간단한 자바 오브젝트)를

Spring에 의해 관리하면서 몇 가지 중요한 개념이 적용되는데,

처음에는 단순히 Java객체의 Wrapper개념으로 생각했지만, 그 이상이었다.

이에 대한 부분은 다음 글에서 다루도록 하겠다.

 

https://en.wikipedia.org/wiki/Singleton_pattern

 

Singleton pattern - Wikipedia

From Wikipedia, the free encyclopedia Design pattern in object-oriented software development A class diagram exemplifying the singleton pattern. In Object-oriented programming, the singleton pattern is a software design pattern that restricts the instantia

en.wikipedia.org