-
(스프링 기본) 15 - 싱글톤 방식의 주의점 (공유필드)개발/Spring 2024. 10. 24. 11:21
싱글톤 객체는 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에
객체는 상태를 유지(stateful)하게 설계하면 안되고 무상태(stateless)로 설계해야 한다.
- 특정 클라이언트에 의존적인 필드가 있으면 안됨.
- 특정 클라이언트가 값을 변경하는 필드가 있으면 안됨.
- 가급적 읽기만 가능해야 함
- 필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등을 사용해야
- 스프링 빈의 필드에 공유값을 설정하면 큰 장애 발생할 수 있음. (주의!!★)
class StateFulServiceTest { @Test void statefulServiceSingleton() { 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); //ThreadB: B사용자 20000원 주문 stateFulService2.order("userB", 20000); //ThreadA: A사용자 주문 금액 조회 int price = stateFulService1.getPrice(); System.out.println("price = " + price); } static class TestConfig { @Bean public StateFulService stateFulService() { return new StateFulService(); } } }
여기서 둘 다 모두 같은 객체를 바라보고 있기 때문에(싱글톤)
order 처리를 한 후 getPrice()를 하면 A 사용자가 주문 금액을 조회해도 20000원이 나온다.
StatefulService 의 price 필드는 공유되는 필드인데, 특정 클라이언트가 값을 변경한다. (문제발생)
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; }
@Test void statefulServiceSingleton() { ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class); StateFulService stateFulService1 = ac.getBean(StateFulService.class); StateFulService stateFulService2 = ac.getBean(StateFulService.class); //ThreadA: A사용자 10000원 주문 int userAPrice = stateFulService1.order("userA", 10000); //ThreadB: B사용자 20000원 주문 int userBPrice = stateFulService2.order("userB", 20000); //ThreadA: 사용자A 주문 금액 조회 // int price = stateFulService1.getPrice(); System.out.println("userAPrice = " + userAPrice); System.out.println("userBPrice = " + userBPrice); // Assertions.assertThat(stateFulService1.getPrice()).isEqualTo(20000); }
따라서 이를 int 값으로 반환값으로 아예 돌려주게 만들고
원래 코드에서 직접 값을 출력하게 한다.
출처 : 김영한 스프링 핵심 원리 - 기본편
'개발 > Spring' 카테고리의 다른 글
(스프링 기본) 17 - 컴포넌트 스캔 (0) 2024.10.24 (스프링 기본) 16 - @Configuration과 싱글톤 (바이트코드 조작) (0) 2024.10.24 (스프링 기본) 14 - 싱글톤 컨테이너 (0) 2024.10.24 (스프링 기본) 13 - 싱글톤 패턴 (0) 2024.10.23 (스프링 기본) 12 - 웹 애플리케이션과 싱글톤 (0) 2024.10.23