해결된 질문
작성
·
657
0
현재 스프링 빈 싱글톤 방식 파트 강의를 수강 중입니다.
강의 중 싱글톤 방식의 문제점에 대해 아래와 같이 이해하였습니다.
public class StatefulService {
// private int price; // 상태를 유지하는 필드
public int order(String name, int price){
System.out.println("name = " + name + " price" + price);
//this.price = price; //여기가 문제!
return price;
}
// public int getPrice() {
//// return price;
// }
}
@Test
void statiefulServicesingleton() {
ApplicationContext ac = new AnnotationConfigApplicationContext(testConfig.class);
StatefulService statefulService1 = ac.getBean(StatefulService.class);
StatefulService statefulService2 = ac.getBean(StatefulService.class);
//ThreadA : A사용자가 10000원 주문
//statefulService1.order("userA", 10000);
int userAPrice =statefulService1.order("userA", 10000);
//ThreadB : B사용자가 20000원 주문
//statefulService2.order("userB", 20000);
int userBPrice =statefulService2.order("userA", 10000);
//ThreadA : 사용자A가 주문 금액 조회
// int price = statefulService1.getPrice(); // 10000원 조회해야 하는데??
System.out.println("price = " + userAPrice);
// Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
Assertions.assertThat(userAPrice).isEqualTo(10000);
}
스프링 빈에 등록된 인스턴스(StatefulService)에 공유필드(price)가 있는 경우,
추가로 참조하는 인스턴스(statefulService2)로 인해 값이 변경될 수 있고 큰 버그를 초래할 수 있다.
위와 같은 개념을 익히다보니 자연스럽게 DTO의 공유필드가 떠올랐습니다.
처음에는 DTO는 일반적으로 필드를 사용하니 문제 되지 않나? 했는데 스프링 빈에 등록된 경우에만 문제가 된다고 이해하였습니다. (제가 잘못 이해했는지도 궁금합니다 ㅎㅎ)
그렇다면 혹시 DTO를 스프링 빈에 등록하는 경우가 만에 하나라도 있을까요?
DTO를 스프링 빈에 등록한다면 동일한 문제가 생길 것 같아서요.
답변 1
1
안녕하세요, 김주희 님! 공식 서포터즈 codesweaver 입니다.
네 말씀하신 것처럼 싱글톤 객체의 필드는 공유 문제가 생깁니다. 그래서 스프링 컨테이너에 등록하는 빈은 필드로 상태를 관리하지 않도록 작성합니다. (반드시 필드에 보관해야 한다면 setter는 제공하지 않고 생성자를 통해 값을 할당하며, 그 값을 바꿀수 없도록 제공합니다(=불변객체))
DTO를 스프링 빈으로 사용하는 경우라면 아마, 앱 전체에서 어떤 값을 공유함과 동시에 런타임에서 변경할 수 있다는 요구사항 때문일텐데요. 이 경우 static 을 활용하여 요구사항을 해결할 수 있습니다 .그래서 DTO를 빈으로 등록하는 경우는 거의 없습니다.
감사합니다.