티스토리 뷰
등장배경
스프링 없이 순수 java 코드로 짜면, DI 컨테이너(이전 게시물 참고)는 클라이언트가 요청을 보낼 때마다 새로운 객체를 만들어서 반환한다. 가령 고객의 트래픽이 초당 100만큼 발생하면 초당 100개의 객체가 생성되고 소멸된다. 따라서 메모리 낭비가 심하다.
이를 해결하려면 객체를 하나만 만들어 놓고 클라이언트들이 동일한 객체를 요청하면 이 객체를 반환해서, 모든 클라이언트가 하나의 객체를 공유하게끔 하면 된다. 이것이 바로 싱글톤 패턴이다.
위 코드는 싱글톤 패턴을 자바코드로 구현하는 방법 중 하나이다. static 영역에 객체를 하나 만들어 놓고, 이 객체를 사용하려면 getInstance() 메소드를 반드시 이용하게 만든다. 그리고 생성자를 private으로 선언해서 다른 곳에서 이 객체를 생성하지 못하게 한다.
구현은 복잡하지 않지만, 위와 같이 순수 자바 코드로 구현하면 문제점이 있다.
- 싱글톤 패턴 구현을 위한 코드가 많이 들어간다. e.g. private 생성자, getInstance() 등...
- 클라이언트가 구체 클래스에 의존하게 된다. i.e. 객체가 필요하면 구체 클래스로 가서 getInstance()를 호출해야 함
- private을 사용하기 때문에 자식 클래스를 만들기 어렵다. -> 즉, 유연성이 떨어진다.
- 기타 등등...
스프링
스프링은 싱글톤의 장점은 살리고, 문제점은 제거한 상태로 싱글톤 패턴을 편리하게 사용할 수 있게 해준다.
다시 말해, 싱글톤 패턴의 문제점은 없애고(싱글톤을 위해 별도 코드를 추가하지 않아도 되며, DIP, OCP를 준수하며, private 생성자를 사용하지 않는다.) 객체 인스턴스를 하나만 생성해서 관리한다.
싱글톤 패턴 사용시 주의사항
싱글톤 패턴은 객체 인스턴스를 하나만 생성해서 공유하기 때문에, 싱글톤 객체는 상태를 유지(stateful)하게 설계하면 안된다. 즉, 싱글톤 객체는 항상 무상태(stateless)하게 설계해야 한다.
이를 어길 시, 치명적인 문제가 발생할 수 있다! (실무에서 종종 발생한다고 한다)
stateless 하려면?
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
- 가급적 읽기만 허용해야 한다.
- 지역변수, 파라미터, ThreadLocal 등을 사용한다.
문제 상황 예시
싱글톤 패턴을 적용해서 위와 같은 객체가 클라이언트에게 공유된다고 가정하자. clientA가 10000원을 주문하고, clientB가 바로 이어서 20000원을 주문한다. 그리고 clientA가 자신의 주문내역을 확인한다.
clientA는 10000원을 주문해서 price에 10000원이 찍혀야 한다. 하지만 clientB가 공유 영역에서 price를 20000원으로 바꿔놓았기 때문에 clientA의 주문내역은 20000원이 찍히게 된다.
해결방안 - 지역변수를 활용
사진, 내용 출처 : 인프런, 김영한 강사님의 '스프링 핵심 원리 - 기본편' 강좌, 강의자료
'SPRING' 카테고리의 다른 글
EC2에서 SPRING APPLICATION이 돌아가지 않을 때 (FEAT. SWAP MEMORY) (0) | 2021.04.04 |
---|---|
싱글톤 컨테이너 (2) 원리 (0) | 2021.01.21 |
의존관계 주입(DI, Dependency Injection), DI 컨테이너 (0) | 2021.01.18 |
제어의 역전(IoC) (0) | 2021.01.18 |
다형성과 스프링 (0) | 2021.01.14 |
- Total
- Today
- Yesterday
- 백기선
- 토비의스프링
- 디자인패턴
- c++
- 코딩테스트
- 김영한
- 프록시패턴
- AOP
- BOJ
- 자바
- 자바스터디
- provider
- 코테
- ec2
- 스프링
- gracefulshutdown
- 프록시
- 토비
- 서비스추상화
- 객체지향
- 템플릿콜백
- 토비의봄TV
- 메서드레퍼런스
- java
- 예외처리
- OOP
- 데코레이터패턴
- 프로그래머스
- SOLID
- 카카오
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |