| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- 심볼릭 레퍼런스
- java
- getreference
- 파이썬
- stop the world
- dfs
- 어플리케이션 클래스 로더
- 컴포넌트 스캔
- 플랫폼 클래스 로더
- 다이렉트 레퍼런스
- aws saa-c03
- Spring
- 2026 AWS SAA-C03
- AWS SAA-C03 합격후기
- 자료구조
- 코딩테스트
- 자바
- 알고리즘
- 스프링
- 파이썬 문자열 메서드
- 부트스트랩 클래스 로더
- python list method
- 객체지향
- 딕셔너리
- 스프링 컨테이너
- 클래스 로더 계층
- 파이썬 리스트 메서드
- 백준
- python
- BFS
- Today
- Total
클라우드 낚시꾼
[Spring] 싱글톤 패턴과 싱글톤 컨테이너 본문
1. 싱글톤 패턴이 필요한 이유

웹 애플리케이션은 보통 여러 고객이 동시에 요청을 한다. 순수 DI 컨테이너일 경우에는 고객이 요청을 보낼때 마다 객체를 생성할 것이다. 이능 굉장한 메모리 낭비를 유발한다. 만약, 고객 트래픽이 초당 100이 나오면 초당 100개 객체가 생성되고 소멸된다. 이런 메모리 낭비 문제 때문에 고객의 요청이 동시에 발생할 경우에는 해당 객체를 딱 1개만 생성하고, 공유하도록 설계할 필요가 있다. 이것이 바로 싱글톤 패턴이다.
2. 싱글톤 패턴과 문제점
public class SingletonService {
// 클래스의 인스턴스가 1개가 되도록 보장한다.
// 구체 클래스에 의존 -> OCP 위반
private static final SingletonService singletonService = new SingletonService();
// 싱글톤 인스턴스를 static 메서드로만 제공한다.
public static SingletonService getInstance() {
return singletonService;
}
// 싱글톤 인스턴스가 여러 개 생성되는 것을 방지하기 위해 private 생성자 이용
private SingletonService() {
}
public static void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
싱글톤 패턴이란 클래스의 인스턴스가 단 1개만 생성되도록 보장하는 패턴이다. 위의 코드는 싱글톤 패턴을 구현한 코드이다. 싱글톤 패턴의 생성자는 private이다. 생성자를 private으로 선언했기에 인스턴스를 외부에서 함부로 생성할 수 없다. 이는 싱글톤 패턴의 구현을 가능하게 했지만, 이로 인해 자식 클래스를 만들기 어려워 졌고 내부 속성을 변경하거나 초기화하기 어렵게 만들었다는 점에서 코드 유연성을 떨어지게 만들었다. 또한, 구현 코드를 보면 멤버가 구체 클래스 의존하기에 OCP를 위반하게 되었다.
3. 스프링 DI 컨테이너는 싱글톤 컨테이너

스프링 DI 컨테이너는 기존 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤(1개만 생성)으로 관리한다. 즉, 스프링 빈은 싱글톤으로 관리된다. 이런 스프링 DI 컨테이너처럼 싱글톤 객체를 관리하는 컨테이너를 싱글톤 컨테이너라고 부른다. 또한, 스프링 DI 컨테이너처럼 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라고 부른다. 스프링 DI 컨테이너 덕분에 싱글톤 패턴을 위한 지저분한 코드가 들어가지 않게 되었고 DIP, OCP, 테스트, private 생성자로 부터 자유롭게 싱글톤을 사용할 수 있다.
4. 싱글톤 방식의 주의점
@Test
@DisplayName("싱글톤 패턴은 stateless로 설계해야 한다.")
public void statefulServiceTest() {
ApplicationContext ac = new AnnotationConfigApplicationContext(StatefulSearchService.class);
// 두 변수가 같은 Bean을 공유하고 있음.
StatefulSearchService searchService1 = ac.getBean(StatefulSearchService.class);
StatefulSearchService searchService2 = ac.getBean(StatefulSearchService.class);
//메시의 검색 내용
searchService1.search("메시", "호날두의 천재성");
//호날두의 검색 내용
searchService2.search("호날두", "메시는 멍청이");
//메시는 "호날두는 천재"라는 자신의 검색 기록을 확인할려고 했다.
//하지만, 어쩌다가 호날두의 검색 기록을 확인하게 되었다.
//싱글톤 객체가 stateful로 설계되었기 때문이다.
Assertions.assertThat(searchService1.getrecord()).isEqualTo("메시는 멍청이");
}
싱글톤 패턴은 무상태로 설계해야 한다. 즉, 왠만해서는 읽기만 가능하도록 만들어야 한다. 왜 그럴까?
검색 기능을 제공하는 싱글톤 객체가 있다고 가정해보자. 이 객체는 검색 기록을 보관하며, 검색 기록을 getter로 확인할 수 있다. 어느날, 메시가 이 객체를 이용해서 "호날두의 천재성"을 검색했다. 그다음 우연하게도 호날두가 "메시는 멍청이"라고 검색했다. 그리고 나서 메시가 검색 기록을 확인하기 위해 getter을 호출했다. 메시는 자신의 검색 기록인 "호날두의 천재성"을 기대했지만, "메시는 멍청이"라는 검색 기록을 보고 의아해한다.
위 이야기가 싱글톤 객체가 stateless하게 관리되어야 할 이유를 보여준다. 싱글톤 객체는 단 1개의 객체가 공유되어 사용되기에 어느 특정 사용자가 정보를 그 객체에 남긴다 하더라도 다른 여러 사용자들에 의해 유지되기 어렵다. 그리고 이것이 큰 장애를 유발 할 수 있다.
5. 마치며 (+ 출처)
이 글에서는 싱글톤 패턴과 싱글톤 컨테이너에 대해 알아 보았다. 또한, 스프링 DI 컨테이너는 싱글톤 컨테이너이며 이 안에서 생성된 빈들이 모두 싱글톤 객체로 관리된다는 것을 알게되었다. 다음 글에서는 스프링 DI 컨테이너에 대해 더 자세히 알아보도록 하겠다.
출처
스프링 핵심 원리 - 기본편 강의 - 인프런
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보세요! 📢
www.inflearn.com
'BE Framework > SpringBasic' 카테고리의 다른 글
| [Spring] 컴포넌트 스캔과 스프링 빈 자동 주입 (0) | 2024.03.16 |
|---|---|
| [Spring] @Configuration과 CGLIB (0) | 2024.03.14 |
| [Spring] 스프링 빈에 대하여 (BeanDefinition + 스프링 빈 조회) (0) | 2024.03.12 |
| [Spring] IoC, DI와 스프링 컨테이너(Spring Container) (0) | 2024.03.12 |
| [Spring] 객체 지향 설계 원칙 SRP, DIP, OCP와 관심사의 분리 (0) | 2024.03.12 |