[Spring] 05-2. 싱글톤 방식의 주의점

지찬우·2023년 1월 7일
0

Spring

목록 보기
17/27
post-thumbnail

이 시리즈는 인프런 강의(김영한 님의 ‘스프링 핵심 원리 - 기본편’)로 공부하며 혼자 기록하고, 사람들과도 공유할 수 있도록 작성하는 글이다. 최대한 추가적인 정보는 공식 홈페이지, 문서를 보며 얻을 예정이다.
(개인적인 생각과 이해가 들어가 있기 때문에 저의 ‘무식함’이 있을 수 있습니다😜 혹시라도 이 글을 보게 되시는 분이 계시다면 잘못된 부분 댓글로 많이 알려주시면 너무 감사하겠습니다!!)

GitHub Repository : https://github.com/jcw1031/spring-core-study


싱글톤 방식의 주의점‼️

객체 인스턴스를 하나만 생성하여 공유하는 싱글톤 방식은 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지(stateful)하게 설계해서는 안 된다! 무상태(stateless)로 설계해야 한다.

싱글톤 객체 설계 주의점

  • 특정 클라이언트에 의존적인 필드가 존재하면 안 된다.
  • 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안 된다. 되도록 읽기만 허용한다.
  • 필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.

주의 : 스프링 빈(싱글톤 빈)의 필드에 공유 값을 설정하면 아주 큰 장애가 발생할 수 있다.

stateful의 경우 발생하는 문제점 예시

stateful 하게 객체를 설계했을 때 발생할 수 있는 문제점을 예시 코드를 통해 살펴보자.

singleton 패키지에 StatefulService 클래스를 만들었다.


StatefulServiceprice라는 공유 필드를 갖고 있다. order() 메서드를 사용해 주문을 생성하면 이 공유 필드에 값이 저장된다. 이렇게 설계했을 때 여러 클라이언트가 요청을 하게 되면 어떤 문제가 발생하는지 테스트해 보자.


테스트를 위한 StatefulServiceTest 클래스를 생성한다.


테스트 클래스 내부에 테스트용 구성 클래스를 static class를 사용해 만든다.

@Configuration을 붙이지 않았다. 왜 AppConfig에는 어노테이션을 사용하고, TestConfig에는 @Bean 어노테이션만 사용했는지 궁금했다. 인프런에도 나와 같은 질문에 대한 질문 글이 있길래 참고해 봤다. 다음 시간에 @Configuration에 대해 공부하기 때문에 그 내용을 공부하면 @Configuration을 사용했을 때와 사용하지 않았을 때의 차이를 알 수 있다.

테스트 코드를 작성한다. TestConfig를 기반으로 하는 컨테이너를 생성하고 getBean()을 통해 두 개의 StatefulService 인스턴스가 빈을 참조하도록 한다. 싱글톤이 보장되기 때문에 두 인스턴스가 참조하는 빈은 같다.


사용자 A가 먼저 10000원의 주문을 생성하고, 그 후에 사용자 B가 20000원의 주문을 생성했다.


사용자 A의 주문 금액을 조회해 보자. 금액이 10000원이어야 하지만, 공유 필드를 사용했기 때문에 당연하게도 사용자 B가 주문한 금액이 다시 저장되었기 때문에 테스트가 실패한다.

실제로는 쓰레드가 사용되어야 하지만 해당 예제는 아주 간단하게 테스트한 것이다.


공유 필드를 사용하지 않고 아래처럼 주문을 생성하면 바로 금액을 return해야 정상적으로 조회가 된다.


이처럼 특정 클라이언트가 값을 변경하는 공유 필드가 존재하면 문제가 발생한다. 실무에서 이런 경우가 종종 발생하는 경우가 있다고 한다.

따라서 공유 필드를 항상 조심하도록 하자. 스프링 빈은 항상 무상태(stateless)로 설계하자.


오늘 학습한 내용은 짧지만 매우 중요하고, 우리가 개발을 할 때 주의해야 할 내용이었다. 다음 시간에는 앞에서 언급했던 @Configuration 어노테이션의 역할을 알아본다.

profile
좋은 개발자가 되자.

0개의 댓글