Post

[Lecture - 김영한님(스프링 핵심 원리 - 기본편)] 싱글톤 방식의 주의점

inflearn에서 김영한님 강의를 들으면서 내용을 정리해보자.
스프링 핵심 원리 - 기본편


싱글톤 방식의 주의점

  • 싱글톤 패턴이든 스프링 같은 싱글톤 컨테이너를 사용하든, 객체 인스턴스를 하나만 생성해서 공유하는 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지(stateful)하게 설계하면 안된다.
  • 무상태(stateless)로 설계해야 한다.
    • 특정 클라이언트에 의존적인 필드가 있으면 안된다.
    • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
    • 가급적 읽기만 가능해야 한다.
    • 필드 대신에 자바에서 공유도지 않는 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.
  • 스프링 빈의 필드에 공유 값을 설정하면 정말 큰 장애가 발생할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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);
}
  • 실제 쓰레드는 사용하지 않고, ThreadA가 사용자A 코드를 호출하고, ThreadB가 사용자B 코드를 호출한다 가정한다.
  • StatefulService의 price 필드는 공유되는 필드인데, 특정 클라이언트가 값을 변경한다.
  • 사용자A의 주문금액은 10,000원이 되어야 하는데, 20,000원이라는 결과가 나온다.
  • 공유필드는 매우 조심해야 한다.
  • 스프링 빈은 항상 무상태(stateless)로 설계해야 한다.
This post is licensed under CC BY 4.0 by the author.

© Yn3. Some rights reserved.