싱글톤 방식을 사용할 때 주의점이 있나요?
안녕하세요.
싱글톤 컨테이너를 배우면서, 중요한 주의점을 학습하였습니다.
싱글톤 방식을 잘못 사용하면 실무에서 커다란 문제를 만들 수 있습니다!
실제로 몇 년에 한 번씩은 정말 해결하기 어려운 큰 문제가 터진다고 합니다.
싱글톤 방식의 잘못된 사용은 바로 'stateful(상태유지)'입니다.
싱글톤 객체 인스턴스에 특정 상태를 유지하면 안 됩니다.
여러 사용자가 같은 싱글톤 인스턴스에 접근하기 때문에, 특정 클라이언트에 의존적인 필드가 있으면 안 됩니다.
싱글톤 객체는 가능하면 읽기만 가능해야 하고, 값을 수정하면 안 됩니다.
이처럼 특정 상태를 유지하지 않는 것이 stateless(무상태)입니다.
싱글톤 방식을 사용하려면 stateless를 보장해야 합니다.
스프링에서도, 스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있습니다!!
stateful 싱글톤으로 문제가 발생하는 예시 코드를 봅시다.
StatefulService는 싱글톤으로 관리되는 클래스입니다.
// 싱글톤 방식에서 상태를 유지할 경우 발생하는 문제점 예시
public class StatefulService {
private int price; // 상태 유지 필드
public void order(String name, int price){
System.out.println("name= "+name+" price: "+price);
this.price = price; //여기가 문제!
}
public int getPrice(){return price;}
}
price 필드의 상태가 유지되고 있습니다.
유저의 주문이 들어오면 가격 정보가 싱글톤 객체에 저장됩니다.
여러 유저가 동시에 접근하면 어떻게 될까요?
아래 테스트 코드를 봅시다.
public class StatefulServiceTest {
@Test
void statefulServiceSingleton(){
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean("statefulService", StatefulService.class);
StatefulService statefulService2 = ac.getBean("statefulService", StatefulService.class);
//Thread A: A 사용자 10000원 주문
statefulService1.order("userA", 10000);
//Thread B: B 사용자 20000원 주문
statefulService2.order("userB", 20000);
//Thread A: A 사용자 주문 금액 조회
int price = statefulService1.getPrice();
System.out.println("price = "+price);
}
static class TestConfig{
@Bean
public StatefulService statefulService(){
return new StatefulService();
}
}
}
사용자 A는 만원을 주문하였으나 price를 확인하면 20,000원이 나옵니다!!
여기서는 price 필드가 공유되면서 특정 클라이언트가 값을 변경하므로 문제가 발생하였습니다.
공유 필드를 주의해서 사용하고, 무상태로 설계해야 합니다.
위의 코드처럼 this로 필드를 변경하지 말고, 바로 return 하거나 주문 객체를 만들어서 따로 관리해야 합니다.
인프런 '스프링 핵심 원리 - 기본편' 강의를 듣고 공부하며 정리한 자료입니다.
잘못된 부분은 피드백 주시면 감사하겠습니다.
글 읽어주셔서 감사합니다 :-)
참고자료
[1] 스프링 핵심 원리 - 기본편, 섹션 5. 싱글톤 컨테이너 https://www.inflearn.com/course/스프링-핵심-원리-기본편
'Spring > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
7-1. 스프링 의존관계 주입 4가지 방법 (0) | 2022.01.08 |
---|---|
6-1. 컴포넌트 스캔 (0) | 2022.01.07 |
5-1. 싱글톤 컨테이너 + static method (0) | 2022.01.06 |
4. 스프링 컨테이너와 스프링 빈 + 람다식, Map 데이터 전체 조회 (0) | 2022.01.05 |
3-2. 스프링 핵심 원리 이해2 - 객체 지향 원리 이용(스프링 컨테이너) + 프레임워크 vs 라이브러리 (0) | 2022.01.03 |
댓글