1. 싱글톤이란?
싱글톤(Singleton)은 특정 클래스의 인스턴스를 프로그램 전체에서 단 하나만 생성되도록 보장하는 디자인 패턴이다.
일반적으로 객체를 생성하면 new를 사용할 때마다 새로운 인스턴스가 만들어진다.
MyClass a = new MyClass();
MyClass b = new MyClass();
이 경우 a와 b는 서로 다른 객체이다.
하지만 싱글톤으로 설계된 클래스는 여러 곳에서 사용하더라도 하나의 인스턴스만 공유해서 사용한다.
2. 싱글톤은 어디에 사용할까?
싱글톤은 애플리케이션 전체에서 하나만 존재해도 되는 객체에 사용할 수 있다.
대표적인 예시는 다음과 같다.
① 설정(Configuration) 객체
프로그램 전체에서 공통으로 사용하는 설정 정보를 관리하는 객체이다.
애플리케이션
├─ A 기능 ─┐
├─ B 기능 ─┼──> 하나의 설정 객체
└─ C 기능 ─┘
각 기능마다 설정 객체를 새로 만들 필요가 없기 때문에 하나를 공유할 수 있다.
② 로깅(Logger)
애플리케이션 곳곳에서 로그를 기록할 때 사용하는 로거 객체도 하나를 공유해서 사용할 수 있다.
log.info("회원 가입 요청");
log.info("로그인 요청");
log.error("서버 오류");
여러 곳에서 로그를 기록하지만 로깅을 위해 객체를 계속 새로 생성할 필요는 없다.
③ Spring Bean
Spring에서는 기본적으로 Spring Container가 Bean을 Singleton Scope로 관리한다.
예를 들어 다음과 같은 서비스가 있다고 하자.
@Service
public class MemberService {
}
Spring이 이 클래스를 Bean으로 등록하면 기본적으로 하나의 MemberService 객체를 생성하고 관리한다.
그리고 다른 객체에서 의존성 주입을 요청하면 Spring Container가 관리하고 있는 Bean을 주입해준다.
@RequiredArgsConstructor
@Service
public class MemberController {
private final MemberService memberService;
}
이때 MemberController가 MemberService를 직접 new해서 만드는 것이 아니다.
Spring Container가 관리하고 있는 MemberService Bean을 주입해준다.
Spring Container
│
▼
MemberService 객체 하나 생성
│
├──> Controller에 주입
├──> 다른 Service에 주입
└──> 다른 곳에서도 필요하면 같은 Bean 사용
이런 구조로 동작한다.
Spring에서는 개발자가 직접 싱글톤 패턴을 구현하지 않아도 Spring Container가 Bean의 생명주기와 객체 생성을 관리하면서 기본적으로 Singleton 방식으로 Bean을 관리해준다.
3. 싱글톤의 장점
① 객체 생성 비용 절약
객체를 계속 새로 만들지 않고 하나를 공유하기 때문에 객체 생성에 필요한 비용을 줄일 수 있다.
② 메모리 절약
동일한 객체를 여러 개 생성하지 않기 때문에 불필요한 메모리 사용을 줄일 수 있다.
③ 공통 객체 관리
애플리케이션 전체에서 하나의 객체를 공유해야 하는 경우 편리하게 사용할 수 있다.
4. 싱글톤의 단점
싱글톤이라고 해서 무조건 좋은 것은 아니다.
하나의 객체를 여러 곳에서 공유하기 때문에 객체의 상태(State)를 잘못 관리하면 문제가 발생할 수 있다.
public class Singleton {
private String username;
}
여러 사용자가 동시에 이 객체를 사용한다면 한 사용자의 정보가 다른 사용자의 정보로 변경될 수 있다.
사용자 A
↓
username = "userA"
사용자 B
↓
username = "userB"
사용자 A의 정보가
userB로 바뀌어버릴 가능성
싱글톤 객체는 여러 요청이 동시에 접근해도 문제가 발생하지 않도록 공유 상태를 신중하게 관리해야 한다.
5. 싱글톤과 Spring의 관계
Spring을 공부하면서 싱글톤을 이해하는 것은 매우 중요하다.
Spring에서는 Bean을 기본적으로 Singleton Scope로 관리한다.
MemberService service = new MemberService();
이렇게 하면 new를 실행할 때마다 새로운 객체가 생성된다.
Spring에서는 의존성을 주입받는다.
@RequiredArgsConstructor
@Service
public class MemberController {
private final MemberService memberService;
}
이 경우 Spring Container가 MemberService Bean을 관리하고, 필요한 곳에 해당 Bean을 주입해준다.
Spring에서는 개발자가 직접 Singleton 클래스를 만들어 관리하기보다는 Spring Container가 객체의 생성과 생명주기를 관리하도록 맡기는 것이 일반적이다.
'TIL' 카테고리의 다른 글
| Spring MVC의 ArgumentResolver 등록하고 사용하기 (0) | 2026.07.27 |
|---|---|
| Java Enum 활용하기 - 계산기 과제로 이해하는 Enum (0) | 2026.07.24 |
| JPA N+1 문제란? (왜 생기고 어떻게 해결할까?) (0) | 2026.07.15 |
| [트러블슈팅] 고객 조회 시 주문 통계(총 주문 수 / 총 구매 금액) 추가하기 (0) | 2026.07.14 |
| [Spring] MVC에서 자주 사용하는 객체와 어노테이션 정리 (0) | 2026.07.08 |