프로그래밍/Spring

[ Spring ] DI 컨테이너 싱글톤 방식의 문제점

Yanoo 2022. 2. 5. 01:30
728x90
반응형

<인프런의 김영한님의 강의를 보고 정리한 내용입니다>

 

싱글톤 방식은 여러 클라이언트가 하나의 같은 인스턴스를 공유하기 때문에 상태를 유지하게(stateful)하게 설명하면 안된다. 이유를 보면,

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;
    }
}

이렇게 작성하고

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);

        Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
    }

    static class TestConfig {

        @Bean StatefulService statefulService() {
            return new StatefulService();
        }
    }
}

테스트 코드를 작성했을 때, 내가 원하는 사용자A의 price는 10000이지만 이 코드의 결과를 보면 20000원이 나오게 된다. 이러면 큰 장애가 발생한 것이다.

 

그래서 싱글톤인 상황이므로 stateless하게 코드를 작성해야 한다.

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;
    }

}
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원 주문
        int userAPrice = statefulService1.order("userA", 10000);
        //ThreadB: B사용자 20000원 주문
        int userBPrice = statefulService2.order("userB", 20000);

        //ThreadA: 사용자A 주문 금액 조회
        System.out.println("userAPrice = " + userAPrice);

    }

    static class TestConfig {

        @Bean StatefulService statefulService() {
            return new StatefulService();
        }
    }
}

이렇게 수정해야 한다.


 

728x90
반응형