🧐강의🧐
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard
· 싱글톤 객체는 상태를 유지(stateful)하도록 설계해서는 안됨 : 여러 클라이언트가 같은 객체를 공유하기 때문
➡️ 무상태(stateless)로 설계 !!
》 특정 클라이언트에 의존적인 필드 X
》 특정 클라이언트가 값을 변경할 수 있는 필드 X (가급적 읽기만)
》 필드 대신 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등 사용
☑️ 문제 상황
· 공유 필드의 값을 특정 클라이언트가 변경할 수 있을 때
// 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;
}
}
// StatefulServiceTest
class StatefulServiceTest {
@Test
void statefulServiceSingleton() {
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean(StatefulService.class);
StatefulService statefulService2 = ac.getBean(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("A price = " + price);
assertThat(statefulService1.getPrice()).isEqualTo(20000);
}
static class TestConfig {
@Bean
public StatefulService statefulService() {
return new StatefulService();
}
}
}
➡️ 공유 필드인 StatefulService 의 price 필드의 값을, 특정 클라이언트가 값을 변경하면서 발생한 장애
✅ 해결 방법
· 스프링 빈은 항상 무상태(stateless)로 설계하기 !!
// StatefulService
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;
// }
}
// StatefulServiceTest
class StatefulServiceTest {
...
@Test
void statefulServiceSingleton() {
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean(StatefulService.class);
StatefulService statefulService2 = ac.getBean(StatefulService.class);
// Thread A : A 사용자 10000원 주문
int userAPrice = statefulService1.order("userA", 10000);
// Thread B : B 사용자 20000원 주문
int userBPrice = statefulService2.order("userB", 20000);
// Thread A : A 사용자 주문 금액 조회
// int price = statefulService1.getPrice();
System.out.println("A price = " + userAPrice);
// assertThat(statefulService1.getPrice()).isEqualTo(20000);
}
}
'Spring > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
[컴포넌트 스캔] @Component, @Autowired - 의존 관계 자동 주입 (0) | 2023.12.05 |
---|---|
[싱글톤 컨테이너] @Configuration - 싱글톤 보장 (0) | 2023.12.01 |
[싱글톤 컨테이너] 싱글톤 패턴의 문제를 해결하는 스프링 컨테이너 (0) | 2023.11.29 |
[스프링 컨테이너와 스프링 빈] BeanDefinition - 스프링 빈 설정 메타 정보 (0) | 2023.11.25 |
[스프링 컨테이너와 스프링 빈] 다양한 설정 형식 지원 - 자바 코드, XML (0) | 2023.11.24 |