ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스프링/Spring] 스프링 싱글톤 멀티스레드 환경에서의 주의사항
    Spring 2021. 8. 6. 16:13

    기본적으로 스프링에서는 오브젝트를 IoC컨테이너를 통해 싱글톤으로 관리한다.

    이로 인해 얻는 장점도 많으나, 그에 따른 주의사항도 요구된다.

     

    싱글톤 멀티스레드 환경 주의사항

    싱글톤으로 관리되는 오브젝트는 멀티스레드 환경에서 여러 스레드가 동시에 접근해서 사용할 수 있다.

    따라서 상태 관리에 주의를 해줘야 되는데, 만약 싱글톤 오브젝트가 상태정보(ex 인스턴스 변수)를 내부에 가지고 있게 되면, 다중 사용자의 요청에 의해 저장할 공간이 하나 뿐인 싱글톤 오브젝트에 서로 값을 덮어 쓰게 되거나, 자신이 입력하거나 저장하지 않은 값을 읽어올 수 있다. 따라서 싱글톤 오브젝트는 인스턴스 필드(변수) 값을 변경하고 유지하는

    상태유지 방식으로 만들면 안 된다. 이를 주의하지 않으면 개발자 혼자 테스트하고 사용할 때는 문제가 전혀 없지만 실제로 서버에 배포하고 여러 사용자가 사용하게 되면 심각한 문제가 발생할 수 있다.

     

    그렇다면, 각 요청에 대한 정보나 서버로부터 생성한 리소스나 데이터는 어떻게 다뤄야 될까?
    이때는 파라미터, 로컬 변수, 리턴 값 등을 이용하면 된다. 메서드 파라미터나, 메서드 안에서 생성되는 로컬 변수는 매버 새로운 값을 저장할 독립적인 공간이 만들어지기 때문에 싱글톤이라고 해도 값을 덮어쓸 일은 없다.

     

    잘못된 예

    public class UserDao {
        
        private User user;
        
        public User get(String id){
            ...
            this.user = new User();
            ...
            return this.user;
        }
        
    }

    위 코드를 보면 User DTO를 인스턴스 필드로 선언하여 사용하고 있는데.. 물론 이렇게 스프링을 사용할 개발자는 없겠지만..

    이런식으로 사용한다고 가정하면 멀티스레드 환경에서 위에서 설명한대로 심각한 문제가 발생할 수 있다.

     

    올바른 예

    public class UserDao {
        
        public User get(String id){
            User user = new User();
            return user;
        }
    
    }

    대부분이 이렇게 사용하고 있겠지만.. 이런식으로 User를 인스턴스 필드로 선언하지 않고 메서드 스코프 안에서 인스턴스화를 하면 개별적인 저장 공간을 만들기 때문에 문제가 되지 않는다.

     

    참고

    • 이일민, 「토비의 스프링 3.1(Vol. 1 스프링의 이해와 원리)」, 에이콘출판 (2012)

    댓글