본문 바로가기
스프링(부트)/스프링 내용 정리

멀티 쓰레드 환경과 스프링 빈

by doflamingo 2021. 1. 6.

멀티 쓰레드 환경과 스프링 빈

스프링 빈은 대부분 Singleton 패턴으로 생성되어 Application Context에 의해서 관리된다.

즉, 모든 Controller, Service, Repository는 하나의 인스턴스만 갖고 있는 것이다.

그런데 스프링 환경자체는 멀티 쓰레드인데 어떻게 Thread-Safe를 유지할 수 있을까 궁금해졌다.

정답부터 말하면 Thread-Safe하지 않다. 단지, Thread-Safe하도록 코드를 짤 뿐이다.

일단 구조를 Spring에서 요청이 들어오면 그 요청은 각각 하나의 쓰레드가 맡게 된다.

스프링빈과 멀티쓰레드

즉 모든 쓰레드는 스프링 빈을 공유하고 내부의 멤버변수도 공유하게 되는 것이다.

하나의 예를 보자

@RestController
public class UserController {

    private final UserRepository userRepository;
    private Long n = 0L;

    public UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @GetMapping(value = "/hello")
    @Transactional
    public Long getUser() throws NotFoundException, InterruptedException {
        return userRepository.save(new User(++n,"user"+n)).orElseThrow(() -> new NotFoundException("존재하지 않습니다."));
    }
}

단순히 repository에 저장하는 코드이다.

(물론 실제로는 id를 저렇게 생성하는 일은 없겠지만 잘못된 예시를 보여주기 위해서 id를 하나씩 증가시켜준다고 가정한다.)

로직상으로 봤을 때는 "/hello" 요청이 들어올때마다 user가 저장되고 id값이 하나씩 증가한다.

/hello 요청

그러나 문제는 요청이 동시에 들어왔을 때 생긴다.

100명의 유저가 동시에 요청한다고 부하테스트를 넣었을 때 동일한 id값이 들어가는 것을 알 수 있다.

동일한 아이디가 DB에 들어감

즉, Thread-Safe하지 않다는 뜻이다.

그렇다면 그동안 왜 문제없이 사용했을까?

그 이유는 객체가 상태를 가지지 않는 불변객체였기 때문이다.

 

우리가 보통 사용하는 @Controller, @Service같은 곳에서 사용하는 객체들은 주입을 받아서 사용하고 내부적으로 멤버 변수를 가지고 변화시키지 않는다.

 

다시 말해, 위의 n처럼 요청이 들어올 때마다 n값이 변하는게 아니라 한번 생성자를 통해 주입받은 후 그 객체 자체는 가지고 있는 멤버변수의 상태값을 변화시키지 않는 코드이다.

 

그러므로 스프링빈을 Thread-Safe하게 사용하기 위해서는 스프링 빈으로 주입되는 클래스는 모두 불변 객체여야한다.

아니면 스프링빈의 스코프를 Prototype으로 만들면 해당 빈이 불릴때마다 새로운 객체가 생성되게 된다.

 

출처 https://beyondj2ee.wordpress.com/2013/02/28/%EB%A9%80%ED%8B%B0-%EC%93%B0%EB%A0%88%EB%93%9C-%ED%99%98%EA%B2%BD%EC%97%90%EC%84%9C-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B9%88-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD/

https://alwayspr.tistory.com/11

'스프링(부트) > 스프링 내용 정리' 카테고리의 다른 글

Servlet과 Spring MVC  (0) 2021.01.07
JPA (Java Persistence API)  (0) 2021.01.05
[스프링] Spring Data  (0) 2020.05.24
[스프링] Handler Interceptor  (0) 2020.05.03
[스프링] Spring MVC 예제 및 단위테스트  (0) 2020.04.26

댓글