1. 싱글톤이 필요한 이유
스프링으로 웹 애플리케이션을 만들다 보면 서비스나 리포지토리 같은 객체를 여러 번 생성할 필요가 없는 경우가 많습니다.
요청이 올 때마다 객체를 새로 만들면 메모리를 불필요하게 사용하게 되고 객체 생성 비용도 계속 발생합니다.
그렇다면 객체를 하나만 만들어서 공유할 순 없을까요?
이것이 바로 싱글톤 패턴(Singleton Pattern)입니다.
2. 싱글톤 패턴이란
싱글톤 패턴은 애플리케이션 전체에서 객체를 하나만 생성하도록 보장하는 방법입니다.
다음과 같은 코드로 싱글톤 패턴을 구현할 수 있습니다.
public class SingletonService {
private static final SingletonService instance = new SingletonService();
private SingletonService() {}
public static SingletonService getInstance() {
return instance;
}
}
생성자를 private으로 막아 외부에서 new를 못 하게 하고 getInstance()를 통해서만 객체를 가져오게 합니다.
이렇게 하면 객체는 하나만 생성됩니다.
3. 싱글톤 패턴의 문제점
싱글톤 패턴은 객체를 하나만 쓰는 목적은 달성하지만, 설계 관점에서 여러 문제가 있습니다.
3-1. DIP 위반
클라이언트는 항상 getInstance()를 통해서만 객체를 가져와야 합니다.
즉, 구체 클래스에 강하게 묶입니다.
3-2. OCP 위반
싱글톤 구현 방식을 변경하면 해당 클래스를 사용하는 모든 코드가 함께 수정되어야 합니다.
3-3. 테스트하기 어려움
객체를 직접 생성하므로 mock 객체로 대체하기 어렵습니다.
테스트 간에 상태가 공유될 위험도 있습니다.
정리하면,
싱글톤 패턴은 편해 보이지만 규모가 커질수록 유지보수와 테스트에 불리한 구조가 됩니다.
4. 싱글톤 컨테이너의 등장 (스프링의 방식)
스프링은 이 문제를 싱글톤 컨테이너라는 방식으로 해결합니다.
싱글톤을 직접 구현하지 말고, 스프링 컨테이너가 대신 관리하게 하자
즉, 개발자는 평범한 객체(POJO)만 작성하고 객체를 몇 개 만들지, 어떻게 관리할지는 스프링 컨테이너에 맡깁니다.
5. 스프링 컨테이너의 싱글톤 방식
스프링에서 빈(bean)은 기본적으로 싱글톤 스코프입니다.
MemberService memberService1 = ac.getBean("memberService", MemberService.class);
MemberService memberService2 = ac.getBean("memberService", MemberService.class);
위 코드에서
memberService1과 memberService2는 같은 객체입니다.
하지만 우리는 싱글톤 패턴을 직접 구현하지 않았습니다.
중요한 차이점
객체는 하나지만 클라이언트는 싱글톤이라는 사실을 몰라도 됩니다.
이로 인해 DIP, OCP를 지킬 수 있고 테스트도 훨씬 쉬워집니다.
6. 싱글톤 컨테이너 사용 시 주의할 점
싱글톤 컨테이너에서 가장 중요한 원칙은 무상태(stateless) 설계입니다.
public class StatefulService {
private int price; // 상태를 저장하는 필드
public void order(String name, int price) {
this.price = price; // 문제 발생 지점
}
public int getPrice() {
return price;
}
}
이 객체는 하나만 생성되어 여러 요청이 공유합니다.
// Thread A
statefulService.order("userA", 10000);
// Thread B
statefulService.order("userB", 20000);
price는 공유 필드입니다. 이는 마지막 요청 값으로 덮어씌워집니다.
-> 사용자 A가 잘못된 값을 보게 될 수 있습니다.
올바른 설계 방식
- 필드에 상태를 저장하지 않고
- 파라미터와 반환값만 사용합니다
public int order(String name, int price) {
return price;
}
이렇게 하면 여러 요청이 동시에 와도 문제가 발생하지 않습니다.
7. 정리
싱글톤 패턴은 객체를 하나만 쓰기 위한 방법이지만 설계 원칙을 위반하기 쉽고 테스트와 확장에 불리합니다.
스프링은 이를 싱글톤 컨테이너로 해결합니다.
객체 관리는 컨테이너가 담당하고, 개발자는 인터페이스와 역할에만 집중하면 됩니다.
단, 싱글톤 빈은 반드시 무상태로 설계해야 합니다.
스프링에서 말하는 싱글톤은 개발자가 클래스 안에서 구현하는 기술이 아니라,
컨테이너가 기본적으로 적용해 주는 객체 관리 방식입니다.
'스프링 > 개념' 카테고리의 다른 글
| [빈 시리즈-3] 조회 대상 빈이 2개 이상일 때 (0) | 2026.01.12 |
|---|---|
| [빈 시리즈-2] 스프링은 언제 의존관계를 주입하는가 (0) | 2026.01.12 |
| [빈 시리즈-1] 스프링 빈은 어떻게 등록되는가 (1) | 2026.01.09 |
| 커서 기반 페이징(Cursor-based Pagination) (0) | 2025.05.25 |